Summary
A long-lived chrome-devtools-mcp server (spawned by an AI coding-agent CLI via npm exec chrome-devtools-mcp@latest) attached to an existing Chrome with --browserUrl steadily grows its JS heap until it hits the default ~4GB V8 heap limit and aborts. The npm exec wrapper process dies alongside it (unhandled-rejection path → uv_kill), so each event leaves a pair of crashed node processes.
This looks distinct from #1192 / #1214: those were --autoConnect-mode collector leaks fixed in March/April — and indeed we saw ~3 months of clean operation after those fixes. The leak reported here reappeared with 1.2.0+ in --browserUrl mode.
Environment
- chrome-devtools-mcp: crashes observed on 1.2.0 and 1.4.0 (resolved fresh via
npm exec chrome-devtools-mcp@latest on each start)
- Invocation:
npm exec chrome-devtools-mcp@latest -- --browserUrl=http://127.0.0.1:<port> --experimentalScreencast
- node v23.6.0 (Homebrew), macOS 15.7.2 (Apple Silicon)
- Chrome: current stable, attached via CDP (
--browserUrl), long-lived instance
Workload profile
The server runs for hours-to-days under an agent that repeatedly: takes snapshots, runs frequent evaluate_script polling, and records repeated screencast_start / screencast_stop cycles against a canvas/WebGL-heavy page.
Observed behavior
Seven crash events over 19 days (2026-06-13 → 2026-07-01), all with the identical signature. Time-to-crash shrinks as automation load increases — process lifetime went 2.7 days → 12.7 h → 3.9 h across the last three events, consistent with a load-proportional leak rather than a fixed-rate one.
Faulting thread (named chrome-devtools-mcp), from the macOS crash report:
libsystem_c.dylib abort
node node::OOMErrorHandler(char const*, v8::OOMDetails const&)
node v8::internal::V8::FatalProcessOutOfMemory(...)
node v8::internal::Heap::FatalProcessOutOfMemory(char const*)
node v8::internal::Heap::CollectGarbage(AllocationSpace, GarbageCollectionReason, ...)
node v8::internal::IncrementalMarkingJob::Task::RunInternal()
node node::PerIsolatePlatformData::RunForegroundTask(...)
libuv uv__async_io → uv__io_poll → uv_run
(Other events show the same FatalProcessOutOfMemory via MinorGCJob / mark-compact — i.e., GC can no longer reclaim; the heap is genuinely retained, not fragmentation.)
Secondary: when the server aborts, the parent npm exec wrapper crashes too, inside PromiseRejectReactionJob → node::Kill/uv_kill — a crash-on-crash in the wrapper's rejection handling that might be worth a defensive fix on its own.
What I've ruled out
- Not system memory pressure: no jetsam kill; the stack is V8's internal heap-limit abort.
- Not the screencast temp-file path: frames are written to disk (
fs.mkdtemp → mp4), so suspicion falls on CDP session/protocol-object retention under sustained evaluate_script + screencast churn.
- 1.5.0 changelog contains no related fix, so filing this.
Happy to provide
Full (redacted) .ips crash reports for all seven events, Crashpad minidumps, or a run with --heapsnapshot-near-heap-limit instrumentation if that helps pinpoint the retained objects.
Summary
A long-lived
chrome-devtools-mcpserver (spawned by an AI coding-agent CLI vianpm exec chrome-devtools-mcp@latest) attached to an existing Chrome with--browserUrlsteadily grows its JS heap until it hits the default ~4GB V8 heap limit and aborts. Thenpm execwrapper process dies alongside it (unhandled-rejection path →uv_kill), so each event leaves a pair of crashednodeprocesses.This looks distinct from #1192 / #1214: those were
--autoConnect-mode collector leaks fixed in March/April — and indeed we saw ~3 months of clean operation after those fixes. The leak reported here reappeared with 1.2.0+ in--browserUrlmode.Environment
npm exec chrome-devtools-mcp@lateston each start)npm exec chrome-devtools-mcp@latest -- --browserUrl=http://127.0.0.1:<port> --experimentalScreencast--browserUrl), long-lived instanceWorkload profile
The server runs for hours-to-days under an agent that repeatedly: takes snapshots, runs frequent
evaluate_scriptpolling, and records repeatedscreencast_start/screencast_stopcycles against a canvas/WebGL-heavy page.Observed behavior
Seven crash events over 19 days (2026-06-13 → 2026-07-01), all with the identical signature. Time-to-crash shrinks as automation load increases — process lifetime went 2.7 days → 12.7 h → 3.9 h across the last three events, consistent with a load-proportional leak rather than a fixed-rate one.
Faulting thread (named
chrome-devtools-mcp), from the macOS crash report:(Other events show the same
FatalProcessOutOfMemoryviaMinorGCJob/ mark-compact — i.e., GC can no longer reclaim; the heap is genuinely retained, not fragmentation.)Secondary: when the server aborts, the parent
npm execwrapper crashes too, insidePromiseRejectReactionJob→node::Kill/uv_kill— a crash-on-crash in the wrapper's rejection handling that might be worth a defensive fix on its own.What I've ruled out
fs.mkdtemp→ mp4), so suspicion falls on CDP session/protocol-object retention under sustainedevaluate_script+ screencast churn.Happy to provide
Full (redacted)
.ipscrash reports for all seven events, Crashpad minidumps, or a run with--heapsnapshot-near-heap-limitinstrumentation if that helps pinpoint the retained objects.