`performance_stop_trace` throws on traces over ~512 MB since the 1.2 GB buffer default

Author: thomasbachemCreated Sep 9, 2026Updated Sep 14, 2026
Labelsp2

Description of the bug

performance_stop_trace throws Error: Cannot create a string longer than 0x1fffffe8 characters on any trace whose decoded JSON passes V8's maximum string length of 536,870,888 characters, which for trace JSON means essentially that many bytes – about 512 MB.

parseRawTraceBuffer() decodes the entire recording into one string before parsing it (new TextDecoder().decode(buffer) in src/processors/PerformanceTrace.ts), so since #2614 set bufferSize to 1.2 GB the buffer takes more than twice what that decode can hold. #2614 raised it to keep longer recordings from overflowing the old 200 MB default, which stayed under the cap – so the ceiling moved rather than lifted, from a trace truncated at overflow (#2499) to no analysis at all.

That decode sits above the try that turns a parse failure into a TraceParseError, so instead of There was an unexpected error parsing the trace: … the client gets the bare Node error, naming neither the trace nor its size. A filePath is saved before the parse, so its save line still comes back and the raw trace stays locatable – without one nothing of the recording survives.

Reproduction

heavy.html, forced reflow in a requestAnimationFrame loop:

<!doctype html>
<div id="host"></div>
<script>
  const host = document.getElementById('host');
  for (let i = 0; i < 200; i++) {
    const node = document.createElement('div');
    node.textContent = 'row ' + i;
    host.appendChild(node);
  }
  const rows = [...host.children];
  function thrash() {
    for (let round = 0; round < 100; round++) {
      for (const row of rows) {
        row.style.width = (100 + (round % 50)) + 'px';
        void row.offsetHeight;
      }
    }
    requestAnimationFrame(thrash);
  }
  requestAnimationFrame(thrash);
</script>
  1. navigate_page to that file
  2. performance_start_trace with reload: false and autoStop: false
  3. Wait 15 seconds
  4. performance_stop_trace

The size is what decides it rather than the wait, so on slower hardware the wait has to go up – pass a filePath and the saved file says where a run landed. On an M5 Pro five seconds records 373,928,200 bytes – 70% of the cap – and returns the usual summary and insights, fifteen seconds records 1,110,091,776 bytes, about twice it, and throws.

Expectation

A default buffer that cannot record more than the tool can then read. Failing that, an error naming the size, so it is clear whether anything survived.

MCP configuration

Driven by a scripted stdio client, server started as `--isolated --no-usage-statistics --workspace

` – the workspace only so a `filePath` outside the OS temp dir validates, and it reproduces with and without `--headless`

Chrome DevTools MCP version

1.9.0

Chrome version

153.0.8010.36, launched by the server

Coding agent version

None for the repro above, which runs from a scripted client. First hit from Claude Code in the Claude macOS app 1.49585.0

Model version

Claude Opus 5

Chat log

None

Node version

v24.19.0

Operating system

macOS

Source: ChromeDevTools/chrome-devtools-mcp