Skip to content

Windows: the engine dies without a message (0xC0000409) when the commit limit is reached; the RAM checks only look at physical RAM #1607

Closed as not planned

Description

@masel

Summary

On Windows the engine exits without a message (exit code 3221226505 = 0xC0000409) when the system's commit charge
reaches the commit limit (RAM + page file), even with several GiB of physical RAM still available. The RAM admission
for the conversation cache and session checkpoints reads only ullAvailPhys (src/core/conversation_memory.cpp,
conversation_available_memory()), so it admits allocations the commit limit then refuses; expert_source.cpp already
reads ullAvailPageFile. Under WDDM the card's VRAM is charged to the commit as well (#141), so a page file setup
accepts (it warns below 4 GB, #60) can leave almost no headroom for the larger models.

Reproduced 6 times at two page-file sizes, with and without WSL; every crash came within 0.1 GiB of the limit and
right after a prompt read.

Setup

  • RTX 5060 Ti 16 GB (driver 616.92), Ryzen 7 5700X3D, 80 GB RAM (79.9 GiB visible), Windows 11 Pro 10.0.26200
  • Strata 0.1.40.3 (engine and server), release build
  • unsloth UD-IQ4_XS (55.4 GiB of experts), config as setup writes it but without --resident-budget-gib (see RTX 5000 PRO slow unsloth ud iq4_xs fix #1080):
    --max-context 393216 --rope-scaling yarn --rope-scale 1.5 --kv int8 --kv-resident 32768 --expert-cache auto --spec 4 --pcie-frac 0.20 --spec-min-p 0.70; STRATA_TRACE=1 STRATA_RSS_TRACE=1 in env
  • strata.exe's private bytes: ~78 GiB right after loading, up to 79.2 GiB under load
  • Load: OpenCode 1.18.35 in Docker in WSL 2 on three coding tasks (8-30K-token conversations with tool calls), or the
    same 107 requests captured from that run and replayed from Windows with WSL shut down
  • Commit charge, commit limit, available RAM and strata.exe's private bytes sampled every 5-10 s

Results

Run Page file (commit limit) Load Extra commit Commit max Engine crashes
A 16 GB (95.93 GiB) agentic, WSL + Docker - 95.92 5
B 16 GB (95.93 GiB) replay, WSL off - 92.0 0
b8 32 GB (111.93 GiB) agentic, WSL + Docker 8 GiB 102.48 0
C 32 GB (111.93 GiB) replay, WSL off until 0.8 GiB free 111.86 1

"Extra commit" is a ballast process that commits memory with VirtualAlloc(MEM_COMMIT) and never touches it: the
commit rises, physical RAM does not (checked: +2.00 GiB commit, available RAM unchanged).

  • A vs B: the same requests crash with WSL and Docker taking the last few GiB of commit, and not without them.
  • b8: 30 minutes of the agentic load with the commit 3-6.5 GiB above the 16 GB limit and no crash; the limit, not
    the load, is what fails.
  • C: the crash returns with the larger page file and without WSL once the commit is pushed to the limit.
  • In one more run with the ballast at the limit (17.5 GiB, WSL + Docker), the WSL VM died instead
    (Wsl/Service/0x80072746): whoever allocates next fails.

The samples just before each crash (available RAM, commit, strata.exe private bytes):

A  15:37:23   2.93 GiB   95.84 / 95.93   79.02 GiB  -> 0xC0000409
A  15:41:30   3.21 GiB   95.89 / 95.93   79.05 GiB  -> 0xC0000409
A  15:43:24   4.38 GiB   95.88 / 95.93   78.79 GiB  -> 0xC0000005
A  15:47:00   4.01 GiB   95.88 / 95.93   79.15 GiB  -> 0xC0000409
A  15:49:24   3.96 GiB   95.90 / 95.93   79.04 GiB  -> 0xC0000409
C  01:14:14   7.60 GiB  111.86 / 111.93  78.93 GiB  -> 0xC0000409 (fault offset 0x4eb1e9 in strata.exe)

Windows logged System event 2004 (Resource-Exhaustion-Detector, "virtual memory insufficient") ten times during A,
none during B or b8, and in C two minutes before the crash, for example:

Windows hat diagnostiziert, dass der virtuelle Speicher unzureichend ist. Die folgenden Programme belegten den meisten
virtuellen Speicher: strata.exe (21016) belegt 84826337280 Bytes, vmmemWSL (4584) belegt 4080967680 Bytes und
claude.exe (5908) belegt 623763456 Bytes.

The first occurrence, a day earlier with engine 0.1.40 in the same kind of agentic run, also had five crashes with
the same exit code and event 2004 at the same times.

Where it dies

Every crash came right after a prompt read, before the first decode step, which is where the checkpoints are saved.
The last engine log lines before each crash (STRATA_TRACE):

strata trace: read 1954 tokens (batched) in 7923.8 ms
strata trace: read 16 tokens (windows) in 377.0 ms
strata trace: read 833 tokens (batched) in 6420.5 ms
strata trace: read 65 tokens (batched) in 2379.8 ms
strata trace: read 3276 tokens (batched) in 8030.0 ms
strata verify: capturing the 6-token window (295 MiB of VRAM free)

The engine log has no error line; the server reports the engine stopped unexpectedly (exit code 3221226505).
0xC0000409 fits an allocation that throws where nothing catches it (std::terminate -> fail-fast). The conversation
cache's own catch (std::bad_alloc) in generate.cpp would have logged "allocation failed; skip parking", which does
not appear, so the failing allocation is elsewhere. Minidumps of the six crashes (~240 MB each) are available.

Suggestions

  • Engine, Windows: let conversation_available_memory() (and the session/checkpoint admission that uses it) return
    min(ullAvailPhys, ullAvailPageFile), so a snapshot or checkpoint is skipped when the commit cannot take it.
  • Engine: catch std::bad_alloc around the prompt-checkpoint saves as the conversation cache does, and install a
    std::set_terminate / unhandled-exception handler that writes one line ("out of memory: commit X of Y GiB") to the
    log before exiting, so this case is recognisable.
  • Setup: the page-file warning (below 4 GB) does not catch this case. A check against the model's needs would: experts
    in RAM + VRAM + pinned KV + a margin, compared with RAM + page file. Here: 55.4 GiB experts + 16 GiB VRAM + 4.6 GiB
    KV = 76 GiB of 95.9 GiB before anything else runs.
  • Docs: "System managed" or a larger page file for the larger models on Windows. With 32 GB here (limit 111.9 GiB)
    the same agentic runs had 18 GiB of headroom; the page file's peak use was 1.5 GB.

Activity

  1. masel commented on Oct 9, 2026

    @masel
    Author

    I have rewritten the description above with follow-up measurements, so it can be read on its own. What changed:

    • The "verification" with a 32 GB page file in the first version did not prove much: its commit peaked at 93.96 GiB,
      below the old limit. It is replaced by a run with extra commit (b8: 102.5 GiB, above the old limit, no crash) and a
      reproduction with the 32 GB page file and without WSL (run C: crash at 111.86 of 111.93 GiB).
    • strata.exe's private bytes are ~78 GiB right after loading, not 69 as first written (69 was an engine the server had
      restarted after a crash).

    The conclusion and the suggestions are unchanged.

  2. Niko1221 commented on Oct 10, 2026

    @Niko1221
    Owner

    Thanks for the detailed measurements. Two changes in v0.1.42: the conversation cache and checkpoint admission on Windows now reads min(available RAM, available commit) instead of available RAM only, so a snapshot is skipped when the commit limit cannot take it; and serve start prints the commit left against the commit limit and warns when the planned host allocations (conversation cache budget plus checkpoints and staging) plus a 4 GiB floor do not fit, with the page-file advice. We have not added the catch-all handler that writes one line on a std::bad_alloc / terminate; that stays on the list. The silent 0xC0000409 may still come from an allocation we do not budget, so please send the next crash's engine log if it recurs.

  3. masel commented on Oct 12, 2026

    @masel
    Author

    Re-tested on v0.1.43 (engine 0.1.43), as asked: the silent exit still happens at the commit limit.

    Same reproduction as run C in the description: UD-IQ4_XS without --resident-budget-gib, 32 GB page file (limit 111.93 GiB), WSL shut down, the 107 captured agent requests replayed from Windows, and a ballast process that commits memory without touching it until 0.8 GiB of commit are left (it now ends as soon as the engine exits, so the restart is not starved).

    • Start: strata serve: Windows commit: 24.9 GiB left of a 111.9 GiB limit (RAM + page file) (before the ballast; no warning, as expected).
    • Crash 2 minutes in, on the 4th request: exit code 3221226505 (0xC0000409), commit 111.88 of 111.93 GiB, 7.0 GiB of physical RAM available, strata.exe private 79.1 GiB.
    • Last engine lines (STRATA_TRACE=1):
    strata serve: prompt 11946 tokens = 8665 reused + 3281 read in 8657 ms (379.0 tok/s), 1029 generated in 21122 ms (48.7 tok/s), drafts accepted 681 of 793, 5 checkpoints
    ...
    strata trace: request 14799 0
    strata trace: prompt start 14798 -1
    strata trace: lent 1297 slots for 3072 tokens in 0.8 ms
    strata trace: prompt chunk 0 of 2853
    strata trace: read 2853 tokens (batched) in 8065.9 ms
    

    The full engine log and a minidump are available. With a terminate handler that logs one line, the failing allocation would show up directly.

    Engine log excerpt
    # engine 0.1.43, UD-IQ4_XS, crash 2026-10-12 15:00:40 (exit 3221226505)
    ## start-up (this engine)
    strata generate: memory guard: limit 79.9 GiB (source: meminfo), current 9.2 GiB, reclaimable cache credited 0.0 GiB; available 70.8 GiB (MemAvailable 70.8 GiB), floor 2560 MiB
    strata generate: KV streaming: 32768 of 393216 cells per QSA layer in VRAM, the K/V in 4.64 GiB of pinned RAM
    strata generate: expert arena read unbuffered (0 of 32 probe reads from the file cache; 9.1 GiB available, 87.2 GiB of files)
    strata generate: expert arena: cudaHostRegister PORTABLE ok; large pages refused for 59523465216 B (GetLargePageMinimum=2097152, VirtualAlloc error 1314); using 4 KB pages
    strata serve: Windows commit: 24.9 GiB left of a 111.9 GiB limit (RAM + page file)
    prefill: the CPU share is ON by default for prompt chunks below 1024 tokens (the idle CPU takes some of the experts the GPU would stream; answers can differ slightly from 0.1.40.3, mean KL ~0.004). STRATA_PREFILL_CPU_SHARE=0 turns it off.
    strata serve: STRATA_ROUTE_TAIL_SKIP=7 is ON (default): a missed expert that every token of a verify window routes at rank 7 or lower is skipped (+10..20% decode on 12-16 GB cards that miss experts, answers differ slightly from 0.1.41); STRATA_ROUTE_TAIL_SKIP=0 turns it off
    strata serve: 412 MiB of VRAM free with everything loaded
    ## the last 16 lines before the crash
    strata trace: window 12950 4
    strata trace: window 12954 4
    strata trace: window 12958 4
    strata trace: window 12962 4
    strata trace: window 12966 4
    strata trace: window 12970 4
    strata serve: prompt 11946 tokens = 8665 reused + 3281 read in 8657 ms (379.0 tok/s), 1029 generated in 21122 ms (48.7 tok/s), drafts accepted 681 of 793, 5 checkpoints
    strata serve: decode expert cache hit rate: 65.9% (298778 hits / 453293 lookups); 18237 more read by the GPU over PCIe or from another GPU (3.9% of all 471530 routed)
    strata serve: route tail skip: 262177 missed experts skipped (274907 entries) since the start
    strata serve: KV streaming: 99.86% of 27648696 block reads hit VRAM, 151.2 MiB read from RAM
    strata serve: suffix drafts: 20 windows, 48 of 71 drafts accepted
    strata trace: request 14799 0
    strata trace: prompt start 14798 -1
    strata trace: lent 1297 slots for 3072 tokens in 0.8 ms
    strata trace: prompt chunk 0 of 2853
    strata trace: read 2853 tokens (batched) in 8065.9 ms
    
  4. Niko1221 commented on Oct 13, 2026

    @Niko1221
    Owner

    Thanks for the report. To keep the tracker current we are closing issues older than three days: 0.1.44 is out with a long list of fixes, and many older reports are covered by it or by 0.1.43.1.

    If this still happens on 0.1.44, please leave a comment here with your engine log (and the version line it prints), and we will reopen it. A new issue that links this one works too.

  5. masel commented on Oct 16, 2026

    @masel
    Author

    Still happens on v0.1.44.1 — please reopen.

    Same reproduction as run C in the description and as on 0.1.43 (UD-IQ4_XS without --resident-budget-gib, 32 GB page file, WSL shut down, the 107 captured agent requests replayed from Windows, a ballast that commits untouched memory until 0.8 GiB of commit are left and ends with the engine):

    • Version line: strata generate: session is up (engine 0.1.44.1)
    • Start: strata serve: Windows commit: 23.9 GiB left of a 111.9 GiB limit (RAM + page file) (before the ballast)
    • Crash 2 minutes in: 2026-10-16 13:45:12, exit code 3221226505 (0xC0000409), Application event 1000: faulting module strata.exe, offset 0x5b8c29. Commit 111.83 of 111.93 GiB, 9.5 GiB of physical RAM available, strata.exe private 79.0 GiB.
    • Again right after a prompt read, and again no skip parking, allocation failed or any other memory line in the whole engine run:
    strata serve: prompt 8670 tokens = 7601 reused + 1069 read in 8222 ms (130.0 tok/s), 4227 generated in 98134 ms (43.1 tok/s), drafts accepted 2190 of 2809, 4 checkpoints
    strata serve: decode expert cache hit rate: 71.4% (1421155 hits / 1991766 lookups); 55651 more read by the GPU over PCIe or from another GPU (2.7% of all 2047417 routed)
    strata serve: route tail skip: 281286 missed experts skipped (294200 entries) since the start
    strata serve: KV streaming: 99.88% of 31068768 block reads hit VRAM, 151.2 MiB read from RAM
    strata serve: suffix drafts: 39 windows, 57 of 97 drafts accepted
    strata trace: request 11946 0
    strata trace: prompt start 11945 -1
    strata trace: lent 1341 slots for 3328 tokens in 0.8 ms
    strata trace: prompt chunk 0 of 3276
    strata trace: read 3276 tokens (batched) in 7971.8 ms
    

    So the allocation that fails is still one the admission does not cover, most likely the prompt checkpoints taken after the read (checkpoint_at → conversation_checkpoint_save). The full engine log and the minidump are available.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions