[macOS][Codex Desktop] Chrome rollout tracker loops at >160% CPU when session JSONL exceeds V8 max string length
Codex app version
26.803.61601 (build 6396)
Platform
macOS 27.0 beta (26A5388g), Apple Silicon
Summary
The bundled Chrome-control browser-client.mjs rollout tracker enters a permanent high-CPU/high-allocation retry loop when it attaches to a long-running Codex Desktop task whose rollout JSONL exceeds V8's maximum JavaScript string length.
The observed task remained active and usable, but the Chrome-control Node helper sustained approximately 160-167% CPU until terminated.
Reproduction conditions
- Keep a Codex Desktop task active long enough that its
~/.codex/sessions/.../rollout-*.jsonlgrows beyond Node/V8's maximum string length. - Initialize the bundled Chrome-control browser runtime in that task.
- The rollout tracker discovers the current session file with
fileOffset = 0. - It reads the entire rollout in 64 KiB chunks, concatenates those buffers, and calls
.toString("utf8"). - Conversion fails before the returned offset can be assigned.
- The tracker catches the failure without disabling tracking or advancing the offset, then polls again after 250 ms and repeats from byte zero.
Sanitized measurements from the affected task
- Rollout JSONL size:
1,148,831,430bytes - Bundled Node
buffer.constants.MAX_STRING_LENGTH:536,870,888bytes - JSONL records:
24,675 compactedrecords: 35 records totaling828,221,910bytes- Largest individual record:
33,878,758bytes - Hot helper CPU: approximately
160-167% - Current helper RSS during sampling: approximately
3.8 GiB - Physical-footprint peak:
12.1 GiB - Native stack sample was dominated by asynchronous filesystem reads, ArrayBuffer allocation, and V8 garbage collection.
- The helper held the same rollout file open twice during the loop.
- No macOS thermal or performance warning was reported.
No private task history or browser data is attached.
Relevant installed-runtime behavior
The bundled tracker:
- polls every 250 ms while a rollout is active;
- starts newly discovered sessions at offset zero;
- reads all remaining bytes into an array of 64 KiB buffers;
- concatenates all buffers and converts them into one UTF-8 string;
- updates
fileOffsetonly after that operation returns successfully; - catches processing errors and leaves polling active.
Because the observed rollout is more than twice MAX_STRING_LENGTH, the initial conversion cannot succeed. The saved offset therefore remains zero and each poll repeats the full read/allocation attempt.
Expected behavior
Rollout tracking should remain bounded regardless of task-history size. For example:
- tail only a bounded recent portion when attaching to an existing rollout;
- stream JSONL incrementally rather than materializing it as one string;
- cap each read/parse batch;
- advance or checkpoint the offset safely;
- stop retrying or disable tracking after an unrecoverable size error;
- surface a useful diagnostic instead of swallowing the failure.
Actual behavior
One Chrome-control helper continuously rereads and reallocates the oversized rollout, consuming more than one CPU core and several GiB of memory even after browser operations have finished.
Related issues
- #21134 — long active desktop threads causing CPU/memory degradation
- #18629 — inline browser images inflating/poisoning desktop thread histories
Those reports describe related history growth and long-thread degradation, but not this specific rollout-tracker string-limit retry loop.
2 Comments
Private in-app diagnostics have now been submitted from the affected task with both current session logs and browser tabs/browser logs included.
Feedback ID:
019fdd30-fe5e-75d0-b47e-2d6178bde306This identifier also corresponds to the affected Codex task referenced in the report, which should help correlate the uploaded diagnostics with the oversized rollout and Chrome-helper reproduction.
A ~1.15 GB rollout with a >33 MB individual record is a useful scale case for Codex Rescue. Its discovery/doctor path is intended to stay bounded and never load or mutate the whole rollout.
If you still have that exact session and are comfortable testing a third-party local tool, could you try:
Only use
--latestif the affected rollout is still the latest one; otherwise select it locally fromsessionswithout posting its ID/path. No salvage needed.I’m mainly interested in whether the run stays bounded and whether it reports the oversized persisted payload conservatively. Sanitized status/findings and rough runtime are enough — no raw history, image/base64 data, prompts, paths, IDs, repository content, or secrets.
https://github.com/shleder/codex-rescue