0x00000019 BAD_POOL_HEADER
Windows found a pool header in a state that should be impossible. Microsoft's own description of the cause is unusually blunt - the pool is already corrupted at the time of the request, and this may or may not be due to the caller. That single sentence explains why chasing the driver named in the dump so often leads nowhere.
What you are looking at
Your PC ran into a problem and needs to restart.
Stop code: BAD_POOL_HEADER
In Event Viewer the matching entries look like this:
Log Name: System
Source: BugCheck
Event ID: 1001
Level: Error
The computer has rebooted from a bugcheck. The bugcheck was: 0x00000019 (0x0000000000000003, 0xffffa50c1d2e0000, 0xffffa50c1d2e0000, 0xffffa50c1e4b2100).
What the error actually means
Every block of pool memory carries a header describing its size and state, and those headers sit immediately alongside the data they describe. That layout is efficient and fragile: a driver writing a few bytes past the end of its own allocation lands squarely on the header of the block that follows.
The pool manager validates headers on every operation. When it finds one that contradicts itself or its neighbours, it stops - because a pool with inconsistent bookkeeping will hand out overlapping allocations and corrupt unrelated data.
The crucial point is the ordering. The driver that caused the damage has usually finished and moved on. The crash happens when some later, entirely well-behaved operation touches the damaged block. Microsoft says this outright for several parameter values: the corruption is typically not the fault of the prior owner of the freed block, but of the block preceding it being overrun.
Reading the parameters
Parameter 1 is the violation type and the others change meaning with it. Several of these give you something you can check directly.
| Parameter | What it holds |
|---|---|
| 0x3 | The pool freelist is corrupt. Parameter 2 is the pool entry being checked, parameter 3 the read-back forward link, parameter 4 the read-back backward link. In a healthy list, parameters 2, 3 and 4 are identical - so comparing them yourself tells you immediately how the list was damaged, without a debugger. |
| 0x21 | The data following the pool block being freed is corrupt. Microsoft says this typically means the call stack has overrun the block - which makes this one of the few values where the code that crashed really is the code at fault. Parameter 2 is the pool pointer, parameter 3 the bytes allocated, parameter 4 the corrupted value found after the block. |
| 0x22 | An address being freed has no tracking entry - the call stack is trying to free a pointer that was already freed, or was never allocated. A double free or a wild pointer. Parameter 2 is the address. |
| 0xD, 0xE, 0xF, 0x23, 0x24, 0x25 | The pool header of an already-freed block was modified after it was freed. Microsoft's note here is the important one: this is not typically the fault of the prior owner of that block, but usually of the block preceding it being overrun. All parameters reserved. |
| 0x5 | A pair of adjacent pool entries have headers that contradict each other, and at least one is corrupt. Parameters 2 and 4 hold the two entries. |
| 0x2 | The special pool pattern check failed - the owner has likely corrupted the pool block. You will normally only see this with Driver Verifier's Special Pool enabled, which is the point of enabling it. |
| 0x6 / 0x9 | The pool block header's previous size, or its size, is too large. Parameter 2 is the incorrectly calculated entry, parameter 4 the bad entry that caused the miscalculation. |
| 0x7 / 0x8 / 0xA / 0x20 | The pool block header size is corrupt, or zero. Parameter 4 usually holds the bad pool entry. |
What actually triggers it
A driver mishandling memory, with hardware as the alternative when no driver can be pinned down.
| Cause | How often | Detail |
|---|---|---|
| A driver overrunning its allocation | Common | The classic case, and the reason the named module is so often innocent. A driver writes past the end of its own block and damages the header of the next one; the crash surfaces when something else touches that neighbour. |
| Anti-virus and filter drivers | Common | These allocate and free pool constantly while inspecting file and network activity. A version mismatch after a Windows update produces header corruption reliably. |
| A double free or wild pointer | Occasional | Parameter 1 of 0x22 indicates this specifically - a driver freeing something twice, or freeing a pointer that was never a pool allocation. |
| Failing RAM | Occasional | Microsoft's resolution section says directly that if this bugcheck appears inconsistently, it could be related to faulty physical memory. A flipped bit in a header looks identical to a driver overrun from the pool manager's point of view. |
| Unstable memory settings | Occasional | An XMP or EXPO profile beyond what the memory controller sustains produces intermittent corruption with exactly this signature. |
Narrowing it down
Read the violation type first - it decides whether the crashing code is a suspect or a bystander.
Check parameter 1 and classify
Pull the full parameter set from the bugcheck event:
Get-WinEvent -FilterHashtable @{LogName='System'; Id=1001} |
Where-Object { $_.Message -match '0x00000019' } |
Select-Object TimeCreated, Message |
Format-List
0x21 and 0x22 implicate the crashing call stack directly - the driver in the dump is a real suspect. 0xD, 0xE, 0xF, 0x23, 0x24, 0x25 explicitly do not - the damage came from a neighbouring block, and the named driver is a bystander.
On 0x3, compare parameters 2, 3 and 4
Microsoft states that in a healthy freelist those three values are identical. Read them straight off the bugcheck message.
Which one differs, and by how much, characterises the damage. A value differing from the other two by a single bit is a strong hint at memory rather than a driver - that is what a bit flip looks like. A wildly different value looks more like something overwrote the pointer.
Check whether the named module is consistent
Open several dumps and compare MODULE_NAME. Microsoft warns that !analyze is frequently unhelpful at pinpointing the suspect driver with pool corrupters.
Different modules each time is expected on this bugcheck and does not by itself mean hardware. It means the corruption is landing in different places - which is why Driver Verifier rather than dump reading is the tool that resolves this.
Note whether it is consistent or sporadic
Does it happen predictably under certain activity, or at random intervals with no pattern?
Microsoft's guidance ties inconsistent appearances to faulty physical memory. A reproducible pattern tied to specific software points at a driver; genuinely random occurrences move memory up the list.
Fixes, cheapest first
Microsoft's stated resolution is Special Pool on the suspect driver. That is the right answer and it is worth reaching for early.
Run Driver Verifier with Special Pool
Special Pool positions each allocation so that writing past its end faults immediately, in the driver that did it, rather than damaging a neighbour and surfacing later. That converts this bugcheck from unidentifiable to identifiable, which is precisely the problem it presents.
Full settings and the boot-fail safety flag are in the Driver Verifier guide.
Watch outVerifier deliberately increases crashes and can cause a boot loop. Run
verifier /bootmode resetonbootfailbefore enabling any checks - it makes Verifier disable itself automatically if the machine fails to start, which removes most of the risk. Your manual exit is Safe Mode followed byverifier /reset. Full settings and the escape route are in the Driver Verifier guide.Remove third-party security software
Uninstall third-party anti-virus and run on Windows Defender for a few days. Use the vendor's dedicated removal tool rather than the standard uninstaller - these products routinely leave kernel drivers behind.
Test the memory
Particularly if the crashes are sporadic rather than reproducible. Disable XMP or EXPO first, then run MemTest86 from USB for at least four passes. See the memory testing guide - the built-in Windows tool is not sensitive enough to trust a pass from.
Return memory settings to stock
Disable XMP, EXPO and any manual timings, and run for several days. If the crashes stop, the profile was not achievable on your combination of parts - the modules are probably fine.
Strip back kernel-level software
Uninstall anything that installs a kernel driver and is not essential: RGB and fan utilities, VPN clients, virtual drive software, old printer packages, anti-cheat services from games you no longer play. Then run a clean boot for a day.
When it is the hardware, not Windows
Signals that memory rather than a driver is doing the corrupting:
- The crashes appear at random rather than tied to any activity - Microsoft links this pattern to faulty memory.
- On parameter 1 =
0x3, one of the freelist values differs from the others by a single bit. - MemTest86 reports errors at stock settings.
- Driver Verifier runs for days across every non-Microsoft driver without firing.
- Other corruption-flavoured codes appear too -
0x1A,0xC2,0x13A,0x139. - The machine is running an overclock, undervolt or memory profile.
The single-bit test on parameter 1 = 0x3 is worth knowing. Software errors tend to write plausible-looking garbage or zero; a value that differs from its neighbours in exactly one bit position is what a memory fault looks like, and it is checkable from the blue screen message alone.
Frequently asked
How is this different from BAD_POOL_CALLER?
Timing. 0xC2 BAD_POOL_CALLER means the current request was invalid - the caller did something wrong right now. 0x19 BAD_POOL_HEADER means the pool was already corrupted when the request arrived. That is why the caller is a suspect on 0xC2 and usually a bystander on 0x19. The fix converges anyway: Driver Verifier with Special Pool, then memory testing.
The dump names a Microsoft driver. Does that mean Windows is broken?
No. Microsoft components allocate and free pool constantly, so they are statistically likely to be the ones that touch a damaged block first. Microsoft's own documentation warns that !analyze frequently cannot pinpoint the suspect driver with pool corrupters. Treat the name as where the damage was found, not where it was made.
Why does this seem to happen randomly?
Because the crash depends on which block gets touched after being damaged, and that varies with whatever the machine happens to be doing. The same underlying overrun can crash in a different component, at a different time, on every occurrence. Microsoft ties genuinely random appearances to faulty physical memory - but a driver overrun also produces apparent randomness, which is why Verifier exists.
Can I just reinstall Windows?
It helps if the cause is a badly installed or conflicting driver, which is a fair share of cases. It does nothing for failing memory or an unstable memory profile - and since Microsoft explicitly links sporadic occurrences of this bugcheck to faulty physical memory, testing the RAM before reinstalling is worth the overnight run. A reinstall also destroys the crash history you would need if this turns out to be hardware.
Related errors
- 0x000000C2BAD_POOL_CALLERA driver misused kernel memory allocation. Verifier with pool options finds it reliably.
- 0x0000013AKERNEL_MODE_HEAP_CORRUPTIONThe kernel heap manager caught corruption. Parameter 1 names which kind, precisely.
- GuideDriver Verifier: How to Find a Bad Driver Without Bricking Your BootThe tool that names a bad driver. Plus the boot-fail flag that makes it safe to use.