Skip to content

Cross-Engine GC Memory Corruption: V8 and JSC Crash Under Same Workload (83+ Dumps, 10 Signatures) #27575

Closed as not planned

Description

@balandari

Cross-Engine GC Memory Corruption: V8 and JSC Crash Under Same Workload (83+ Dumps, 10 Signatures)

Preflight Checklist

  • I have searched existing issues and this hasn't been reported yet
  • This is a single bug report
  • I am using the latest version of Claude Code

Summary

Claude Code crashes due to garbage collector memory corruption on both JavaScript engines it ships with:

  • Native (claude.exe): Bun 1.3.10 / JavaScriptCore -- 79+ crash dumps, 6 crash families (F1-F6)
  • npm (@anthropic-ai/claude-code): Node.js 24.13.1 / V8 -- 4 crash dumps, 4 distinct signatures

Two completely different GC implementations produce the same category of failure: use-after-free, stale pointer dereference, and heap corruption during normal operation. Upgrading Bun from 1.3.5 to 1.3.10 did not resolve the JSC crashes. The common denominator is the application workload, not the runtime.

This extends #21875 (our Bun crash investigation with 27 analyzed dumps) and #27356 (@jwhitehead-trafilea's cross-engine hypothesis) with new V8 crash dump evidence from cdb/WinDbg analysis.


Environment

Component Value
OS Windows 11 Pro x64 (Build 26200)
CPU Intel i9-14900HX (32 logical, SSE4.2/AVX/AVX2)
RAM 192 GB
Node.js v24.13.1 (Active LTS, V8 13.6.233.17)
Bun v1.3.10 (embedded in native Claude Code)
Claude Code v2.1.x (native) / current (npm)

Cross-Engine Crash Comparison

Characteristic Bun / JSC (native) Node.js / V8 (npm)
Crash dumps analyzed 27 (full cdb analysis) + 52 via crash reports 4 (full cdb analysis)
Crash families 6 (F1-F6) 4 distinct signatures
Dominant exception c0000005 (Access Violation) c0000005 + c000001d (Illegal Instruction)
Pointer patterns NaN-boxed sentinels (0xFFFE/0xFFFF prefix), near-null Near-null, null+offset, 0xFFFFFFFF sentinel
GC mechanism JSC MarkedBlock sweep UAF V8 concurrent GC heap corruption
Detection CPU fault (F2), Bun internal check (F4), heap manager (F6) CPU fault (3 signatures), V8 self-detected (1 signature)
Process uptime at crash 35 sec -- 73 min 3 min 45 sec -- 5 min 2 sec
Thread at crash Main thread Main thread
Crash path JIT code → napi_close_callback_scope → bmalloc/JSC JIT code → uv_check_stop → MakeCallback → v8::Function::Call
Still crashing on latest? Yes (Bun 1.3.10) Yes (Node.js 24.13.1, latest v24)

V8 Crash Dump Analysis (New Evidence)

Four node.exe crashes captured via ProcDump on Feb 21, 2026 within a 10-minute window. All on Node.js 24.13.1, separate process instances, main thread only.

Dump Uptime Exception Failure Bucket Faulting Instruction
211934 -- c0000005 INVALID_POINTER_READ Read from stale pointer (0xFFFFFFFF sentinel)
212141 -- c0000005 SOFTWARE_NX_FAULT Executed non-executable memory (corrupted JIT code pointer)
212534 5m02s c0000005 INVALID_POINTER_WRITE mov qword ptr [rcx+10h], 0 with rcx=NULL
212933 3m45s c000001d ILLEGAL_INSTRUCTION ud2 at v8::base::OS::Abort (V8 self-detected corruption)

Signature 1: INVALID_POINTER_WRITE (dump 212534)

ExceptionAddress: 00007ff766628660 (node!v8::platform::DelayedTaskQueue::Terminate+0x7c380)
   ExceptionCode: c0000005 (Access violation)
   Parameter[0]: 0000000000000001
   Parameter[1]: 0000000000000010
Attempt to write to address 0000000000000010

CONTEXT:
  rcx=0000000000000000  rdx=0000000000000000
  rip=00007ff766628660  rsp=0000005ca5bfac68

STACK (key frames):
  node!v8::platform::DelayedTaskQueue::Terminate+0x7c380   ← crash (rcx=NULL)
  node!v8::base::debug::StackTrace::ToString+0x18c257
  node!v8::RegExp::GetFlags+0x8d6f3
  node!X509_STORE_set_get_issuer+0x7c08e                   ← V8 internal (symbol noise)
  0x00000193be67727a                                        ← JIT code
  [... deep recursive JIT frames ...]
  node!v8::Function::Call+0x46
  node!node::MakeCallback+0x5e
  node!uv_check_stop+0xde                                   ← libuv check callback
  node!uv_run+0x340                                         ← event loop

V8 attempted to write to offset 0x10 of an object, but the object pointer (rcx) was null. The object was freed by GC while JIT code still held a reference. Deep recursive JIT call stack with 9+ repeated frames at 0x0000020c38f770b8 indicates heavy JavaScript execution at crash time.

Signature 2: V8 Deliberate Abort (dump 212933)

ExceptionAddress: 00007ff7662c2dd3 (node!v8::base::OS::Abort+0x63)
   ExceptionCode: c000001d (Illegal instruction)
Faulting instruction: ud2

STACK (key frames):
  node!v8::base::OS::Abort+0x63                             ← deliberate ud2
  node!v8::base::CPU::has_sse41+0x8463                      ← V8 internal (symbol noise)
  node!v8::RegExp::GetFlags+0x3aa33
  node!v8::WasmStreaming::Unpack+0xd479
  node!v8::Platform::SystemClockTimeMillis+0x3028f
  0x000001dd9fe7733a                                        ← JIT code
  [... deep recursive JIT frames with alternating patterns ...]
  node!v8::Function::Call+0x46
  node!node::MakeCallback+0x5e
  node!uv_check_stop+0xde
  node!uv_run+0x340

V8 detected its own heap corruption and deliberately crashed via ud2 (undefined instruction) in OS::Abort. This is V8's self-defense mechanism -- it found inconsistent heap state during verification and aborted rather than continuing with corrupt data.

Common V8 Crash Pattern

All four V8 dumps share:

  1. Entry path: uv_run → uv_check_stop → node::MakeCallback → v8::Function::Call → JIT code
  2. Main thread only -- all background threads (V8 workers, libuv workers, delayed task scheduler) idle at crash time
  3. Deep recursive JIT call stacks -- heavy JavaScript execution with repeated frame patterns
  4. Short-lived processes (3-5 min) -- corruption manifests quickly under workload

The four signatures are four symptoms of one underlying problem: V8's GC corrupts live object references under this workload. Which symptom appears depends on which corrupted pointer V8 touches first:

Symptom What V8 Did
Read stale sentinel Dereferenced freed object → read poisoned memory
Execute heap data Followed corrupted code pointer into data region
Write through null Object pointer freed/zeroed → null deref at field offset
Deliberate abort V8's own verification caught inconsistency

JSC Crash Families (Established Evidence)

From #21875 -- 27 full memory dumps analyzed via cdb, classified into 6 families:

Family Exception Frequency Mechanism
F2: JSC GC UAF c0000005 81.5% NaN-boxed tagged pointer dereference after GC freed object
F4: FAST_FAIL c0000409 11.1% Bun internal corruption check → __fastfail(7)
F5: Partial Pointer c0000005 3.7% Corrupted pointer with valid prefix, garbage suffix
F6: Heap Double-Free c0000374 3.7% Windows heap manager detects LFH double-free
F1: Worker Thread c0000005 Rare Worker thread cleanup UAF
F3: Heap Address c0000005 Variable Freed heap memory dereference

All families trace through napi_close_callback_scope in Bun's N-API implementation. F4 stack traces show 3 frames through this function before the abort. F6 confirms the mechanism: napi_close_callback_scope → pas_system_heap_free → RtlFreeHeap → HEAP_FAILURE_SEGMENT_LFH_DOUBLE_FREE.

Bun 1.3.10 still produces these crashes. The Bun 1.3.7 JSC upgrade did not resolve the underlying issue.


V8 CVE Context

Node.js 24.13.1 ships V8 13.6.233.17 (Chrome 136 vintage). Three CVEs fixed in later Chrome versions pattern-match our V8 crash signatures:

CVE Description Fixed In Matching Signature
CVE-2025-6558 JIT compilation race condition causing memory corruption Chrome 137 SOFTWARE_NX_FAULT (corrupted JIT pointer)
CVE-2025-9864 Use-after-free in V8, heap corruption Chrome 140 INVALID_POINTER_READ (stale sentinel)
CVE-2025-13042 Inappropriate implementation leading to heap corruption Chrome 142 General heap corruption

These CVEs have not been cherry-picked to Node.js 24's V8 branch. Node.js 24.13.1 is the latest v24 release.

These CVEs may contribute to the V8-side crashes, but they do not explain the JSC-side crashes. The cross-engine nature of the problem points to the application workload as the primary factor.


Reproduction

Non-deterministic. Crashes typically occur within 1-10 minutes of sustained use.

  1. Run Claude Code (native or npm) on Windows x64
  2. Use normally -- tool calls, subprocess spawning, multi-agent orchestration
  3. Process crashes between 35 seconds and 73 minutes

Higher subprocess spawn volume widens the race window. Our workflow involves multi-agent orchestration (hundreds of spawns per session). Other users report crashes at lower activity levels (#27320, #26984).


The Question

Two independent GC implementations (JSC and V8) both corrupt memory under Claude Code's workload. The runtimes have no shared GC code. The shared factors are:

  • Heavy async subprocess spawning (child_process.spawn / equivalent)
  • Deep callback nesting across async boundaries
  • Rapid object allocation and deallocation during tool call processing
  • N-API native addon lifecycle operations during active GC

What in Claude Code's workload is generating this GC pressure? Specifically:

  1. Is there instrumentation that can profile the allocation rate and object churn during tool call processing?
  2. Are there N-API cleanup operations that could be deferred or batched to reduce GC contention?
  3. Has this crash pattern been observed in Anthropic's internal testing on Windows?

Full ProcDump captures (.dmp files) are available for all 83+ crashes if the engineering team wants them for analysis.

Related Issues

Claude Code Version

2.1.50+ (npm), latest native

Platform

Anthropic API (Claude Max)

Operating System

Windows 11 Pro x64 (Build 26200)

Note

This issue was written by Claude (Opus 4.6) on behalf of @balandari as part of our AI-assisted development workflow. Full ProcDump captures (.dmp files, 83+ crashes totaling ~113 GB) are available on request.

Activity

  1. github-actions commented on Feb 22, 2026

    @github-actions

    Found 3 possible duplicate issues:

    1. Repeated Bun v1.3.5 segfaults -- 78 crashes, root cause identified (Windows + WSL) #21875
    2. [BUG] N-API addon lifecycle crash — same segfault on both Bun and Node.js runtimes #27356
    3. Bun 1.3.10 segfault on Windows x64 — JSC GC use-after-free persists from #21875 #27003

    This issue will be automatically closed as a duplicate in 3 days.

    • If your issue is a duplicate, please close it and 👍 the existing issue instead
    • To prevent auto-closure, add a comment or 👎 this comment

    🤖 Generated with Claude Code

  2. balandari commented on Feb 22, 2026

    @balandari
    Author

    Not a duplicate. This issue extends #21875, #27356, and oven-sh/bun#27003 with new evidence: 4 V8 crash dumps analyzed via cdb showing the same GC corruption pattern occurs on Node.js/V8, not just Bun/JSC. The cross-engine evidence is new and not covered by any of the linked issues.

    Note

    This comment was written by Claude (Opus 4.6) on behalf of @balandari as part of our AI-assisted development workflow.

  3. github-actions commented on Mar 22, 2026

    @github-actions

    Closing for now — inactive for too long. Please open a new issue if this is still relevant.

  4. github-actions commented on Mar 31, 2026

    @github-actions

    This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.

  5. locked as resolved and limited conversation to collaborators on Mar 31, 2026
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

    staleIssue is inactive

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions