Skip to content

copilot.exe hard-crashes on Windows (0xc0000005), losing in-flight turns and corrupting terminal state #4891

Description

@kcuzner

Describe the bug

The CLI terminates with an unhandled access violation during normal use. The process dies
without running its cleanup handler, so two things happen every time:

  1. The in-flight turn is lost. The session records a model.call_start with no
    matching completion, leaving a null assistant response.
  2. The terminal is left unusable until manually reset — mouse clicks and scroll emit
    raw escape sequences as plaintext, and the alternate screen buffer is never exited.
    This indicates the process never emitted \e[?1000l / \e[?1006l / \e[?1049l, which
    confirms abrupt termination rather than any graceful shutdown or Ctrl-C path.
Image

37 crashes between 2026-08-13 and 2026-09-16, across five CLI versions (1.0.79.0,
1.0.81.0, 1.0.82.0, 1.0.83.0, 1.0.85.0), peaking at 9 crashes in a single day (08/28).
This appears to be a regression introduced around 1.0.79 — see Onset below.

One consequence worth flagging up front: server-side, affected sessions record
model.turn_failed followed by abort(abort_reason = "user_abort"), with no
session_error_type or session_error_message. The user did not abort. These crashes
are therefore likely invisible in backend telemetry and may be miscounted fleet-wide as
deliberate user cancellations.

Affected version

GitHub Copilot CLI 1.0.85

Steps to reproduce the behavior

No deterministic reproduction. The crash occurs under sustained normal use, multiple times
per day, on a shell-call-heavy workload.

The one condition that correlates strongly with a subset of crashes ("Mode A" below):

  1. Open two or more sessions in a single copilot.exe process.
  2. Switch repeatedly between them (each switch emits
    Unregistering foreground session / Registering foreground session).
  3. Run a shell-call-heavy workload in those sessions.
  4. After roughly 27+ foreground registrations, the process logs
    Native session event flush exceeded 10000ms; dispatching the host event copy without the ordering barrier and shortly afterwards dies with 0xc0000005.

Note this accounts for only 3 of the 14 crashes that could be classified; the majority
("Mode B") occur with a single session and no prior warning of any kind.

Expected behavior

The CLI should not terminate with an unhandled access violation. Failing that:

  • A crash handler should restore terminal state on abnormal termination (disable mouse
    reporting, leave the alternate screen), so a crash does not leave the terminal unusable.
  • A client crash should be recorded distinctly from a user cancellation, rather than both
    surfacing as abort_reason = "user_abort".

Additional context

Environment

Field Value
OS Microsoft Windows 11 Enterprise 10.0.22631 (Build 22631)
CPU Intel Core i9-14900K
Architecture x86_64 (AMD64)
RAM 63.7 GB (no system memory pressure)
Terminal Mixed — many sessions ran inside neovim's built-in terminal, the remainder in the Windows 11 default console host. Crashes occurred in both.
Shell PowerShell 7.6.0 (Core)
Install source WinGet

Workload is shell-heavy: many powershell tool calls, MCP (github-mcp-server) enabled,
memory disabled by policy.

The terminal host doesn't correlate with particular failure modes. A substantial share
of the affected sessions ran inside neovim's built-in terminal and the rest in the
standard Windows console host, and crashes occurred under both. The exact per-crash split
cannot be given because no terminal or host identification is recorded in the session
events, the process logs, or the Windows event log (see provenance note below).

Three full-process crash dumps were captured (1.12 GB / 1.36 GB / 1.61 GB — resident size
at time of death). All three are Mode A; no Mode B dump has been captured yet.

Onset — likely regression at or near 1.0.79

Period Sessions Crashes
2026-05 15 0
2026-06 14 0
2026-07 39 0
2026-08 85 15 (first on 08/13)
2026-09 114 22

The Windows Application log on this machine retains records back to 2025-08-22, so
pre-08/13 crashes would have been captured had they occurred. 68 sessions across
May–July produced zero crashes
; the first crash is 2026-08-13 on 1.0.79.0.

Caveat: usage also rose over this period, so frequency is confounded — but the complete
absence of crashes in the first three months, against a log that would have recorded them,
still points to a regression rather than a long-standing latent bug.

Crashes per version: 1.0.79 = 7, 1.0.81 = 7, 1.0.82 = 7, 1.0.83 = 13, 1.0.85 = 3.

Exception distribution and recurring fault offsets

Count Exception Meaning
33 0xc0000005 Access violation
2 0xc0000409 STATUS_STACK_BUFFER_OVERRUN — on Windows this is also how __fastfail reports, i.e. how a Rust panic = "abort" typically manifests
2 0x80000003 Breakpoint — likely a debug_assert! / debug assertion

Several offsets repeat, which should make these tractable to localize:

Offset Module Occurrences Versions
0x201 unknown 5 1.0.79, 1.0.81 (x2), 1.0.83 (x2)
0x9ab52e copilot.exe 4 1.0.79, 1.0.81 (x2), 1.0.82
0x66c97c / 0x66c980 copilot.exe 3 1.0.82
0x993270 / 0x993860 copilot.exe 2 1.0.85

Offsets in the unknown-module cases are small or nonsensical (0x0, 0x31, 0x201,
0xffffffffffffffff), consistent with a null/dangling pointer dereference or an indirect
call through a freed vtable.

Full crash inventory (37)

Time (local) Version Exception Module Fault offset PID Dump
08/13 21:24:17 1.0.79.0 0xc0000005 copilot.exe 0x1aa41bd 18712
08/13 21:40:24 1.0.79.0 0xc0000005 copilot.exe 0x1671124 46896
08/14 16:06:50 1.0.79.0 0xc0000005 unknown 0x2a4a4179c8f 31772
08/27 22:04:34 1.0.79.0 0xc0000005 unknown 0x201 3320
08/27 22:20:12 1.0.79.0 0xc0000005 copilot.exe 0x9ab52e 15040
08/28 08:05:04 1.0.79.0 0xc0000005 copilot.exe 0x680834 15940
08/28 08:11:51 1.0.79.0 0xc0000005 copilot.exe 0xb1d596 31652
08/28 08:14:01 1.0.81.0 0xc0000409 copilot.exe 0x222b289 33464
08/28 08:19:14 1.0.81.0 0xc0000005 copilot.exe 0x9ab52e 33464
08/28 08:40:54 1.0.81.0 0xc0000005 unknown 0x7ff80984e9b3 2364
08/28 09:46:58 1.0.81.0 0x80000003 copilot.exe 0x129ce02 37548
08/28 11:14:43 1.0.81.0 0xc0000005 unknown 0x201 40840
08/28 11:15:33 1.0.81.0 0xc0000005 copilot.exe 0x9ab52e 6092
08/28 11:41:20 1.0.81.0 0xc0000005 unknown 0x201 36700
08/31 10:20:12 1.0.82.0 0xc0000005 copilot.exe 0x927233 19160
09/02 10:43:38 1.0.82.0 0xc0000005 copilot.exe 0x66c980 33748
09/03 13:59:30 1.0.82.0 0xc0000005 copilot.exe 0x66c97c 18456
09/03 16:59:47 1.0.82.0 0xc0000005 copilot.exe 0x1b0759e 34824
09/04 08:16:13 1.0.82.0 0xc0000005 copilot.exe 0x66c980 12908
09/04 09:36:04 1.0.82.0 0xc0000005 unknown 0x209005e0c10 30868
09/04 09:44:59 1.0.82.0 0xc0000005 copilot.exe 0x9ab52e 21592
09/08 16:10:29 1.0.83.0 0xc0000409 copilot.exe 0x225c809 38376
09/08 20:25:02 1.0.83.0 0xc0000005 copilot.exe 0x9961e5 5792
09/10 20:54:55 1.0.83.0 0xc0000005 copilot.exe 0x90dad5 30712
09/10 22:13:19 1.0.83.0 0xc0000005 unknown 0x1c150cf73f0 34120
09/10 22:28:40 1.0.83.0 0xc0000005 unknown 0xffffffffffffffff 1348
09/10 22:31:13 1.0.83.0 0x80000003 copilot.exe 0x12ca9c2 16728
09/11 12:01:09 1.0.83.0 0xc0000005 unknown 0x201 7612
09/14 13:13:01 1.0.83.0 0xc0000005 unknown 0x24b83440000 32264
09/14 19:22:33 1.0.83.0 0xc0000005 unknown 0x201 44536
09/14 21:02:11 1.0.83.0 0xc0000005 copilot.exe 0x997c4a 57592
09/14 21:44:28 1.0.83.0 0xc0000005 copilot.exe 0x1b31e1e 45724
09/15 09:02:38 1.0.83.0 0xc0000005 unknown 0x5157dfc909 61700
09/15 09:47:23 1.0.83.0 0xc0000005 unknown 0x0 62204
09/16 16:39:38 1.0.85.0 0xc0000005 unknown 0x31 32112 1.61 GB
09/16 17:08:07 1.0.85.0 0xc0000005 copilot.exe 0x993860 35240 1.36 GB
09/16 17:23:15 1.0.85.0 0xc0000005 copilot.exe 0x993270 49136 1.12 GB

Analysis scope

Of the 37 crashes, 14 have surviving ~/.copilot/logs/process-*.log files (on-disk log
retention begins 2026-09-10; the other 23 predate it). The mode analysis below therefore
covers 14 crashes; the remaining 23 are documented in the inventory but unclassified.

Mode A — event-stream saturation bypasses an ordering barrier (3 of 14 classified)

Across all process logs, exactly three contain:

Native session event flush exceeded 10000ms; dispatching the host event copy without the ordering barrier

Those three PIDs (32112, 35240, 49136) are exactly the three with crash dumps. No
process emitted this warning and survived.

Preceding it, in volume:

[WARNING] [rust:session_bindings::api_session_event_stream] Session event stream lagged while flushing {"skipped":124}
[WARNING] [rust:session_bindings::api_session_event_stream] Session event stream lagged; recovering from the registry snapshot {"skipped":149}

PID 32112: 273 lag warnings, 6,764 events dropped total, largest single drop 817 events.

Key control: PID 34636 logged 544 lag warnings — more than any crashed process —
but zero barrier bypasses, and did not crash. Lag alone is survivable; bypassing the
ordering barrier is what precedes the fault.
This suggests the >10s fallback path that
dispatches "without the ordering barrier" is itself unsafe (use-after-free / data race),
not merely degraded.

Correlate: foreground session re-registration

PID Registrations Unique sessions Lag Bypass Crashed
35240 43 2 209 3 yes
32112 27 5 265 4 yes
49136 27 3 95 3 yes
34636 4 2 544 0 no
others 1–4 1–2 0–38 0 no

PID 35240 toggled between two sessions 43 times in about 16 minutes. Each switch
cleanly Unregisters before Registering, so any leak is downstream of that call.

Supporting symptom: event fan-out amplification.
session.background_tasks_changed is emitted approximately 22x per single powershell
tool call
, including plain synchronous ones, in bursts of roughly 8 duplicates within
1–4 ms. Measured across 20 sessions the ratio holds at 19.4–28.5 per shell call,
independent of file-read volume (sessions with 3 reads and with 229 reads show the same
ratio). One shell state transition producing 22 events looks like unintended fan-out and is
plausibly what saturates the stream. This event does not appear in local
events.jsonl — it exists only in the in-process/ephemeral stream, i.e. precisely the
stream that overflows.

Mode B — crash during an active operation, no stream distress (11 of 14 classified)

The majority of classified crashes, and not explained by Mode A. No barrier bypass,
little or no stream lag, and several hosted exactly one session that was never switched.

PID Registrations Unique sessions Bypass Last recorded event before crash Gap
57592 1 1 0 model.call_start (no completion) 2 s
62204 1 1 0 model.call_start (no completion) 42 s
61700 1 1 0 tool.execution_start (no completion) 92 s
32264 3 2 0 session.background_tasks_changed 6.7 min
45724 1 1 0 (MCP client init logged) 9.3 min
44536 1 1 0 session.managed_settings_resolved 54.6 min
16728 1 1 0 3.2 min

Common signature: a *_start event with no matching completion — the process dies mid
model call or mid tool execution, with no prior warning of any kind.

No root cause identified for Mode B. Given 1.1–1.6 GB resident and the presence of
0xc0000409 / 0x80000003 among exception codes, an allocator or concurrency fault
elsewhere in the native layer seems more likely than the event stream.

Why the 23 pre-09-10 crashes could not be classified

They cannot be sorted into Mode A vs Mode B. The only reliable discriminator is the
barrier-bypass log line, which exists solely in ~/.copilot/logs/process-*.log; on-disk
retention begins 2026-09-10. Three independent substitutes were tested against the 14
known-mode crashes and all failed:

Proxy tested Result
Wall-clock interleaving of sessions near the crash (switching proxy) Rejected. Mode B crashes occupy the highest values (PID 1348: 1169 events / 159 alternations in 20 min) vs Mode A's 31–57. Ranges fully overlap. It measures concurrent processes, not switching within one.
Event-ordering violations in events.jsonl (expected artifact of dispatching without the ordering barrier) Rejected. Zero timestamp inversions across all 257 sessions; forward parent references are spread evenly over unaffected sessions.
Windows Error Reporting stack hashes Unavailable. No copilot.exe reports in %ProgramData%\Microsoft\Windows\WER (53 reports present, none from this application).

Stream lag is also not usable as a stand-in for bypass: PID 34636 logged 544 lag
warnings and 15,828 dropped events without bypassing or crashing, while PID 34120 crashed
with zero lag.

What can be established for the older crashes, from events.jsonl (retained to April):

  • For 15 of 23, a session can be identified that produced its final event shortly
    before the crash and never resumed. In 8 of those 15 the final event is a *_start
    with no completion (assistant.turn_start, model.messages_snapshot), 1–64 s before the
    crash — the same "died mid-operation" signature seen in Mode B.
  • The remaining 8 have no session terminating nearby, most likely because those
    session-state directories were not retained.
  • This signature does not discriminate: Mode A victims die mid-operation too
    (PID 32112's victim died 17 s after model.messages_snapshot).

So the older crashes are usable as frequency and version evidence, and their fault
offsets remain fully valid for symbolization, but they should not be assigned a mode.

Ruled out

Tested and not contributing:

  • Large tool output. Streaming 4.2 MB through a tool call produced no memory growth
    (573 MB -> 553 MB private); the harness already spills oversized output to a temp file.
  • Parallel file reads. view/grep generate essentially no background-task events.
  • Long sessions / high turn counts. One crash occurred after only 4 user turns.
  • Machine-level causes. No correlating Kernel-Power, disk, or network events; crashes
    occur mid-workday, not at sleep/lock transitions; 63.7 GB RAM with no memory pressure.
  • Model provider / backend. No session_error_type / session_error_message recorded
    for any affected session.

Notes on data provenance

  • Crash inventory is from the Windows Application event log (ID 1000), authoritative and
    complete back to 2025-08-22.
  • Session event data is from the Copilot session store; background_tasks_changed counts
    come from the cloud store, as these ephemeral events are not persisted locally.
  • Process-log-based mode classification covers only the 14 crashes since 2026-09-10; disk
    log retention does not extend earlier. Three substitute signals were tested against the
    known-mode crashes and rejected (see the section above).
  • Null assistant responses alone are not a reliable crash indicator — some are genuine
    user cancellations. The event-log crash list is the ground truth.
  • No terminal/host identity is recorded anywhere — not in session.start (which
    carries only cwd, git context, and version), not in the process logs, and not in the
    Windows event log. Sessions therefore cannot be attributed to a terminal emulator after
    the fact. Recording the host terminal at session start would make this class of report
    considerably easier to triage.

Activity

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

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions