Browser tool auto-attaches a screenshot to nearly every Code Mode result, permanently inflating history and app-server memory
What version of the Codex App are you using?
26.818.31338 (build 6892); codex-cli 0.149.0-alpha.4
What subscription do you have?
rate_limits payloads report plan_type: prolite
What platform is your computer?
macOS 26.4, Apple Silicon (arm64), 48 GB RAM
What issue are you seeing?
When the active model runs in code_mode_only mode (e.g. gpt-5.6-sol), every tool call is routed through the node_repl js tool. If the script touches the in-app browser at all, the tool result comes back with a full data:image/png;base64,... screenshot attached — even when the script never asked for one.
Measured over a single ~6.5 hour session:
| | |
|---|---:|
| node_repl :: js calls | 864 |
| calls whose result contained an image | 347 |
| of those, scripts referencing any screenshot/image API | 3 |
| images attached without being requested | 344 (99.1%) |
Example of a script that came back with an image attached — it only reads text:
const tab = await browser.tabs.new();
await tab.goto("http://127.0.0.1:<port>/");
await tab.playwright.waitForTimeout(1500);
nodeRepl.write(await tab.playwright.locator("body").innerText({ timeoutMs: 5000 }));
Downstream effects, all measured:
- Rollout size. That session's rollout reached 306 MB in 6.5 hours; 91% of its bytes were base64 image data (650 images).
- Compaction write amplification. Compaction itself works correctly — the retained-history snapshot rises and falls as expected. But each snapshot re-serializes the retained images. 64 snapshots wrote 188 MB to disk while live retained history peaked at 6.3 MB, i.e. roughly 30x write amplification.
- app-server memory. The
app-serverprocess reached 22.3 GB physical footprint after 3d20h uptime with 21 rollouts open, of which 21.2 GB was compressed/swapped, growing at roughly 5.5 GB/day. On a 48 GB machine this consumed essentially the entire compressor and filled swap. - Disk. The local sessions directory grew from 140 GB to 182 GB in 4 days (378 new rollout files).
Two notes for whoever triages this:
- RSS hides the memory growth. Resident was only ~1.0 GB because the rest was compressed;
vmmap --summary <pid> | grep "Physical footprint"is the metric that shows it. - The heap was dominated by
MALLOC_SMALLlive allocations (20.3 GB across 5188 regions) rather thanMALLOC_LARGE(1.8 GB), so the memory is mostly parsed history structures, not the image blobs themselves.
What steps can reproduce the bug?
- Use a model whose metadata is
tool_mode: code_mode_only(e.g. gpt-5.6-sol), with the bundledbrowserplugin enabled. - In Code Mode, run a script that only reads text from a page and never calls any screenshot or image API — for example the snippet above, against any local or public URL.
- Inspect the resulting
mcp_tool_call_endentry in the session rollout.jsonl. - Its
outputarray contains adata:image/png;base64,...item the script never requested. - Keep working in that session and watch rollout size and app-server footprint grow.
Session ID deliberately omitted — the conversations involved contain confidential work. Happy to supply one privately if it helps.
What is the expected behavior?
Any one of these would address it:
- Attach a screenshot only when the script actually requests one.
- Provide a switch to disable auto-attachment. I could not find one: I checked the bundled
browserplugin'sbrowser-service.mjsand everyNODE_REPL_*/BROWSER_USE_*string in thenode_replbinary, and there is nodisableScreenshot-style option. - Elide or downscale image payloads when writing compaction snapshots, so a retained image is not re-serialized on every subsequent compaction.
- Apply a low
imageDetaildefault to auto-attached images.
Additional information
These mitigations have independent value: the first fixes the source, while the compaction change fixes the ~30x amplification on its own and would still help if auto-attachment turns out to be intentional.
There is also no retention policy for the sessions directory, so all of the above accumulates permanently.
1 Comment
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action