Recurring 0x1E bugcheck in nt!ExpPoolTrackerChargeEntry on Windows 11 25H2 (26100.8655), not fixed by KB5094135

Pat Gordon 90 Reputation points
2026-06-16T05:45:47.4066667+00:00

My Alienware 18 (model AA18250) on Windows 11 25H2 has been blue-screening repeatedly for about five weeks, and I would like it escalated since the latest cumulative update did not fix it.

Failure signature (consistent across 15+ dumps since early May):

  • Fault bucket: AV_nt!ExpPoolTrackerChargeEntry
  • WER failure hash: 6f13343d-8edf-14f9-0269-6df067c74f57
  • Bugcheck 0x1E (KMODE_EXCEPTION_NOT_HANDLED, parameter 1 = 0xc0000005). The same function also surfaces as 0x3B, 0x23, and 0x135 depending on which subsystem trips it.
  • Triggered by many unrelated processes (explorer.exe, svchost.exe, Registry, and others), which points to the shared kernel pool allocator rather than any single third-party driver.

Analysis already done:

  • Faulting instruction is lock xadd qword ptr [r14+r8], rbp, where r8 (expected to be a PoolTrackTable entry pointer) holds different invalid values on each crash. Different garbage each time indicates a software race, not a hardware bit-flip. Caller is nt!ExpAllocatePoolWithTagFromNode+0x52.
  • ETW kernel tracing shows a burst of roughly 700,000 registry/file kernel events per second immediately before each crash (normal heavy load is 10,000 to 50,000 per second), under filesystem-filter pressure.
  • Hardware ruled out: Windows Memory Diagnostic passed two passes, Dell ePSA passed, and NVMe SMART is clean.

Why I am posting: KB5094135 (build 26100.8655, installed 6/13/2026) did not resolve it. It has recurred on this build with the identical signature on 6/14, 6/15, and 6/16.

Request: escalation to the kernel / pool-allocator team referencing failure hash 6f13343d-8edf-14f9-0269-6df067c74f57, confirmation of whether a fix is planned and in which build, and any supported interim mitigation. I can provide minidumps and the ETW capture on request.

Windows for home | Windows 11 | Performance and system failures

22 answers

Sort by: Most helpful
  1. Gary Nebbett 6,536 Reputation points
    2026-07-05T08:28:16.4366667+00:00

    Hello All,

    I suspect that the belief that this problem is due to a locking issue with Microsoft code is probably misplaced. Indeed, Microsoft might not be in a position to address the problem.

    Pat's analysis assumes that there is one "pool tracker table" (PoolTrackTable), but this is not the case on multiprocessor systems: they have one table per processor and PoolTrackTable is just the table for processor 0.

    19: kd> dq nt!PoolTrackTable l 1
    fffff803`d6efe9e0  ffffce0f`c2602000
    19: kd> dq nt!ExPoolTagTables l 1a
    fffff803`d6efa9e0  ffffce0f`c2602000 ffffbd80`3ac41000
    fffff803`d6efa9f0  ffffbd80`3ad00000 ffffbd80`3ad71000
    fffff803`d6efaa00  ffffbd80`3ae40000 ffffbd80`3aea1000
    fffff803`d6efaa10  ffffbd80`3af3d000 ffffbd80`3b000000
    fffff803`d6efaa20  ffffbd80`3b069000 ffffbd80`3b105000
    fffff803`d6efaa30  ffffbd80`3b19b000 ffffbd80`3b235000
    fffff803`d6efaa40  ffffbd80`3b2d0000 ffffbd80`3b366000
    fffff803`d6efaa50  ffffbd80`3b400000 ffffbd80`3b496000
    fffff803`d6efaa60  ffffbd80`3b540000 ffffbd80`3b600000
    fffff803`d6efaa70  ffffbd80`3b680000 ffffbd80`3b700000
    fffff803`d6efaa80  ffffbd80`3b796000 ffffbd80`3b830000
    fffff803`d6efaa90  ffffbd80`3b8c6000 ffffbd80`3b960000
    fffff803`d6efaaa0  00000000`00000000 00000000`00000000
    

    The "one table per processor" design removes the need for the lock management suggested by Pat.

    If there is no room in a per-processor table for a new entry, then an "expansion" table (shared by all processors) is used; this table is adequately protected by locks. As far as I can tell, this expansion table never shrinks (or is removed); the two full dumps available in this thread indicate that the expansion table has not been used (PoolTrackTableExpansion == 0).

    The values that Pat has observed in _POOL_TRACKER_TABLE NonPagedBytes fields (e.g. fffffffffdff47d0 and ffffffffffff9e20) are plausibly correct; there is no requirement to free a pool allocation on the same processor from which it was allocated. Treating these NonPagedBytes values as signed integers and summing across all processors gives reasonable results.

    In the two full dumps, the tag being tracked as CM64. The !poolused debugger extension performs the necessary summation of the individual processor table values.

    5: kd> !poolused 1 CM64
    ........................
     Sorting by Tag
    
                          NonPaged                                Paged
     Tag     Allocs     Frees    Diff       Used     Allocs     Frees    Diff       Used
    
     CM64   2829193   2829191       2        480          0         0       0          0
    

    The instruction that "causes" the exception uses the r14 register, which is not saved in the _KTRAP_FRAME created by KiGeneralProtectionFault; disassembly of ExpPoolTrackerChargeEntry shows that r14 must contain either 0x8 (offset of NonPagedBytes) or 0x20 (offset of PagedBytes). The "Circular Kernel Context Logger" indicates that no interrupt has plausibly taken place between entry into the ExpPoolTrackerChargeEntry routine and the exception. In some of the minidumps, a _CONTEXT structure with valid r14 value at time of exception can be found, showing that r14 contains an expected value.

    nt!ExpPoolTrackerChargeEntry+0x40:
    lock xadd qword ptr [r14+r8],rbp
    

    The !pte command on an address formed by the r8 value plus an assumed r14 value of 0x8 or 0x20, shows that the address writen by the xadd command is valid and writeable:

    5: kd> !pte @r8+8
                                               VA ffff8081a7b9bd58
    PXE at FFFFB65B2D96C808    PPE at FFFFB65B2D901030    PDE at FFFFB65B202069E8    PTE at FFFFB64040D3DCD8
    contains 0A00000125A0F863  contains 0A00000125A10863  contains 0A0000013AC11863  contains 8A000001262E8963
    pfn 125a0f    ---DA--KWEV  pfn 125a10    ---DA--KWEV  pfn 13ac11    ---DA--KWEV  pfn 1262e8    -G-DA--KW-V
    

    The "mystery" (to me) is what caused the general-protection exception.

    According to "Intel 64 and IA-32 Architectures | Software Developer’s Manual", the only reason for a general-protection exception when executing the xadd instruction is "If the memory address is in a non-canonical form". I think that the !pte command demonstrates that this is not the case.

    The limited range of models and CPU types on which the problem has been observed suggests that there is a hardware dependency, so the obligation to resolve the problem does not rest solely on Microsoft.

    Gary

    Was this answer helpful?

    7 people found this answer helpful.

  2. Pat Gordon 90 Reputation points
    2026-06-21T23:56:44.27+00:00

    Posting a full root-cause analysis in case it helps triage, and to ask whether this can be escalated to the kernel / pool-allocator team. Offsets from ntkrnlmp.exe 10.0.26100.8457; still reproduces on 26100.8655 after KB5094135 (installed 2026-06-13). Failure hash 6f13343d-8edf-14f9-0269-6df067c74f57, faulting IP nt!ExpPoolTrackerChargeEntry+0x40 (P2 low bits ...96570, invariant across ASLR bases).

    Summary: use-after-free in the pool tag tracker. nt!ExAllocateHeapPool has a lock-free fast path that locates a _POOL_TRACKER_TABLE entry from a cached PoolTrackTable base and mask, then calls nt!ExpPoolTrackerChargeEntry to atomically update its accounting fields. The tracker table is dynamically expandable: nt!ExpInsertPoolTrackerExpansion publishes the new base/size under ExpTaggedPoolLock, releases the lock, and then frees the old table with nothing waiting for in-flight lock-free readers to drain. A fast-path charge that snapshotted the old base before an expansion computes an entry pointer into the freed/recycled old table and executes lock xadd against it. If that page has been reused, it bugchecks.

    The fault (052826-17906-01.dmp, .cxr at the exception context):

    nt!ExpPoolTrackerChargeEntry+0x40:
    fffff805`bf996570 f04b0fc12c06  lock xadd qword ptr [r14+r8],rbp  ds:002b:ffffa381`b4ba31e8=fffffffffdff47d0
    
    rbp=0000000000000540  r8=ffffa381b4ba31e0  r13=0000000020707249 ("Irp ")  r14=0000000000000008
    

    r8 is a _POOL_TRACKER_TABLE entry pointer; r14=8 selects NonPagedBytes; rbp=0x540 is the allocation size being added. [r8+8] holds fffffffffdff47d0, not a plausible byte total. Bugcheck SYSTEM_SERVICE_EXCEPTION (3B), exception c0000005. Call chain is a routine IRP allocation: ExpPoolTrackerChargeEntry <- ExAllocateHeapPool <- ExpAllocatePoolWithTagFromNode <- ExAllocatePool2 <- IopAllocateIrpPrivate (tag "Irp ") <- a NtQueryInformationProcess / file-name query.

    Cross-dump fingerprint (the use-after-free tell). Same instruction and hash; r8 is invalid a different way each crash, which is what freed-and-reused memory looks like:

    Dump Process Stop r8 what is at r8 now
    052826-17906-01 logioptionsplus 0x3B ffffa381b4ba31e0 freed/reused, [r8+8]=fffffffffdff47d0
    052026-15875-01 Dropbox 0x1E 0072007400730069 not a pointer; r8/r9/r10 = UTF-16 "istr","y\ma","chin", a ...Registry\Machine... path string in that page
    052726-15765-01 svchost 0x23 ffff80805d5b6330 freed/reused, [r8+8]=ffffffffffff9e20
    052826-18250-01 powershell 0x135 via CmpCallbackFatalFilter same root function

    Four processes, four stop codes, one root function. The stop code is just whichever exception handler catches the fault on the way up. The Dropbox dump is decisive: the tracker-entry pointer points into a page that has been recycled into a registry path string.

    Where the bad pointer is produced (nt!ExAllocateHeapPool). The slow path reads the table base fresh under ExpTaggedPoolLock; the fast path uses a cached snapshot and takes no lock:

    mov  rdx, qword ptr [rsp+38h]    ; cached PoolTrackTable base, NO lock
    and  eax, r12d                   ; index &= cached PoolTrackTableMask, NO lock
    lea  rbx, [rax+rax*4]            ; rbx = index*5
    shl  rbx, 4                      ; rbx = index*0x50  (sizeof _POOL_TRACKER_TABLE)
    add  rbx, rdx                    ; entry = base + index*0x50
    mov  r8, rbx
    call nt!ExpPoolTrackerChargeEntry
    

    Where the old table is freed (nt!ExpInsertPoolTrackerExpansion):

    call nt!ExAllocateHeapPages                          ; new larger table -> rdi
    ... memcpy(old -> new) ; memset(tail) ...
    mov  [nt!PoolTrackTableExpansion], rdi               ; +bfcde445 publish new base, lock held
    mov  [nt!PoolTrackTableExpansionSize], r12           ; +bfcde452 publish new size, lock held
    call nt!KeReleaseInStackQueuedSpinLock               ; +bfcde46b release lock
    call nt!ExPoolCleanupExpansionTable(old, oldSize)    ; +bfcde47b FREE old table, AFTER unlock
    

    The publish is correctly serialized under ExpTaggedPoolLock. The defect is that reclamation happens after the lock is released, unprotected against in-flight lock-free readers.

    The race. CPU A (charge) snapshots base+mask with no lock. CPU B grows the table, publishes the new base/mask under the lock, releases, then frees the old table. CPU A computes old_base + index*0x50 and executes lock xadd/lock inc into the freed table.

    Why heavy load is required. A continuous ETW kernel trace shows every crash preceded by a ~3 second burst of ~700,000 kernel events/sec (normal heavy load is 10k-50k/sec), ~42% registry and ~42% file, from a process-creation storm across 24 logical CPUs. That forces tracker-table growth while charges are in flight, and explains the very low public report rate.

    Fix direction. The publish is already serialized; the problem is freeing the retired table immediately after unlock. Most localized fix: defer the free until lock-free readers drain (epoch/generation or an RCU-style barrier) instead of calling ExPoolCleanupExpansionTable right after release. Alternatives: bump a generation counter under the lock on each publish and recheck it on the charge path before the atomic write; or carry the index and recompute the entry from the current base at charge time.

    This is not a single bad unit. Multiple independent users now report the identical hash and faulting offset on the Intel Arrow Lake-HX platform (Core Ultra 9 275HX), across different OEMs and GPUs: Alienware 18, Alienware 16x, and Acer Predator. WER bucket telemetry alone may not surface something this rare; correlated multi-user reports with the same hash through a kernel engineer would. Full kernel dumps, 14 deduplicated minidumps (all same hash), and the ETW captures are available on request.

    Caveat: this is reverse-engineered from optimized release ntoskrnl.exe with public symbols and post-mortem dumps. The fault context, the two-path disassembly, the divergent-r8 fingerprint, and the burst correlation are direct evidence; the exact free/publish ordering in the expansion routine is the one inference the team can confirm internally.

    Was this answer helpful?

    6 people found this answer helpful.

  3. Timothy Lawless 10 Reputation points
    2026-07-09T05:07:41.9833333+00:00

    I found my way here from a post on reddit. I have two systems that have exhibited this problem. We bought two Alienware laptops, model AA16250 last year for Christmas. This is running the Ultra 9 275HX cpu. One laptop began crashing in April, the other one started crashing about two weeks ago. Dell replaced the mainboard on the 1st laptop and that resolved the crashes. I'm going through dell support presently to get the 2nd laptop fixed.

    1. This is a hardware (cpu?) issue. I shared my notes on the Dell forum and Reddit. You must look at the memory.dmp file generated by either a kernel or full dump to diagnose this. The failures are triggered by a locked atomic operation at nt!ExpPoolTrackerChargeEntry+0x40 (the lock xadd qword ptr [r14+r8],rbp instruction). From a memory.dmp file you can see from the !pte command that the address at [r14+r8] in the context of the exception was present, writable, supervisor, and write-back cacheable. From only a mini-dump you can't see this, and one would probably blame corruption of the pool tracking data structures.
    2. The crashes cluster around a particular core. In my first laptop, all but one crash was on core 17. On the 2nd laptop all crashes have been on core 9.

    In the case of my first laptop, demonstrating the behavior from #1 and the clustering from #2 was how I convinced dell to perform a mainboard replacement.

    Based on this thread, I am now wondering if the clustering is not an additional diagnostic pattern. In Bryan's mini-dumps, all but two of the crashes are on core 3. In Tyler's crashes, 3 of the 4 are on 19. This matches my observed clustering on my two laptops. I suspect that this "clustering" may also contribute to making the crashes "look" different, and may hinder identifying this issue in incoming error reports from users. On the 1st laptop, almost all the crashes traced back to a svchost and either NtOpenKeyEx, NtDeleteKey, NtSetValueKey, NtQueryInformationProcess. On the 2nd laptop, all but one crash pointed to DirectX. I was able to write a powershell script that triggered the crash quickly on laptop 1, but it does nothing to laptop 2. The fault is independent of the subsystem, with the constant being the locked atomic operation.

    Finally, this problem seems to have a delayed onset. In my case both systems entered into service at the same time and have been used for gaming daily, yet one didn't crash until 6 months after purchase, and the other started about 4 months after purchase.

    Best of luck,

    --Tim

    Was this answer helpful?

    3 people found this answer helpful.

  4. 放 李 5 Reputation points
    2026-07-01T03:42:34.82+00:00

    Similar problem, crash happens when i playing delta force. dump11.txt This is keep happening since i use the windos11,so i guess this should be considered by microsoft`s engineers.

    Was this answer helpful?

    2 people found this answer helpful.
    0 comments No comments

  5. Lester Bernard Reyes 86,725 Reputation points Independent Advisor
    2026-06-16T09:58:27.23+00:00

    Hi, I'm Bernard. I'm happy to help!

    Can you please upload and share the Minidump files on your PC so I can further examine the root cause of the issue?

     

    Press Windows key + E (To open File Explorer)

     

    Click "This PC" > then follow the file path:

     

    C:\Windows\Minidump

     

    Copy the Minidump files and save them to another location, like the Desktop or Documents.

     

    Then please upload it to Cloud storage like OneDrive or any cloud storage you are using, and please share the shareable link here.

    To upload and share the link using OneDrive:

    Go to this link: https://onedrive.live.com/, then upload the file.

    Then, provide the shareable link by following the steps from this link: https://support.microsoft.com/en-us/office/share-onedrive-files-and-folders-9fcc2f7d-de0c-4cec-93b0-a82024800c07

    Note: This is a public forum. I may respond shortly, but I apologize in advance for any delays. I am simply a fellow user trying to provide helpful insights and information.

    Was this answer helpful?

    1 person found this answer helpful.

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.