VS Code/WSL: repeated compacted snapshots duplicate inline base64 images and cause 1GB+ transcripts / OOM

Open 💬 2 comments Opened Jun 24, 2026 by vu4934108-code

Summary

Long Codex IDE sessions that include screenshots or image messages can grow to
hundreds of MB or more than 1GB. The JSONL transcript stores images as inline
data:image/...;base64,... payloads. During automatic context compaction, those
same image URLs appear to be copied into repeated type: "compacted" records.

This creates a multiplicative storage effect: a small set of unique images can
be duplicated hundreds or thousands of times inside compacted snapshots. When
the VS Code extension restores such a session, codex app-server can consume
multiple GiB of RSS and be killed by the WSL OOM killer.

Environment

  • Component: Codex VS Code IDE extension + bundled codex app-server
  • Extension: openai.chatgpt / Codex - OpenAI's coding agent
  • Extension version: 26.5616.71553
  • Bundled CLI: codex-cli 0.142.0
  • OS: WSL2, Ubuntu 24.04.4 LTS
  • Kernel: 6.6.87.2-microsoft-standard-WSL2
  • Memory: 7.6 GiB RAM, 2.0 GiB swap
  • CODEX_HOME: default ~/.codex
  • Session files: ~/.codex/sessions/**/rollout-*.jsonl

Expected behavior

  • Compacted history should not duplicate large inline image blobs.
  • Image blobs should be de-duplicated, externally referenced, or replaced with

a stable lightweight reference inside compacted snapshots.

  • Restoring a long session should not require loading multiple copies of the

same image data into memory.

Actual behavior

Example local audit results:

  • 39 transcripts scanned.
  • 9 CRITICAL transcripts, 4 HIGH transcripts, 5 MEDIUM transcripts.
  • The 9 CRITICAL transcripts total 8,394,890,728 bytes.
  • Of that, 6,805,785,756 bytes are inline images inside type: "compacted" records.
  • Estimated size after replacing only compacted image URLs with tiny placeholders:

1,590,325,684 bytes.

Largest observed transcript:

  • File size: 1,496,450,263 bytes.
  • Inline image data inside compacted records: 1,258,934,740 bytes.
  • Estimated conservative slim size after replacing compacted image URLs only:

237,795,507 bytes.

Another sample transcript:

  • File size: 884,953,267 bytes.
  • Inline image data inside compacted records: 738,536,666 bytes.
  • Rewriting only compacted image URLs to a tiny placeholder reduced the file to

146,538,695 bytes.

  • JSONL line count stayed unchanged: 45,381 lines.
  • Max line size dropped to about 1.6 MB.

OOM evidence

When opening affected sessions in the VS Code extension, the webview can show:

Codex process errored: Codex app-server process exited unexpectedly (code=unknown, signal=SIGKILL)

WSL kernel log observed:

Out of memory: Killed process ... (codex) total-vm:5980636kB, anon-rss:5273620kB

Reproduction outline

  1. Use Codex VS Code extension in WSL2.
  2. Create a long-running session with many tool calls and several screenshots or image messages.
  3. Let the session continue across multiple automatic context compactions.
  4. Inspect the local JSONL transcript under ~/.codex/sessions/**/rollout-*.jsonl.
  5. Observe repeated type: "compacted" records containing full inline data:image/...;base64,... payloads.
  6. Reopen the session from VS Code recent tasks.
  7. Observe high codex app-server RSS and possible SIGKILL/OOM.

Suggested fix direction

  • Do not embed full image data URLs inside compacted records.
  • De-duplicate image payloads by content hash.
  • Store image blobs once per transcript or in a blob cache and reference them.
  • During compaction, preserve enough metadata for model context and UI replay without copying the full base64 payload repeatedly.

Privacy note

The affected transcript contents include private project work and screenshots,
so I cannot attach full raw JSONL files publicly. I can provide:

  • Redacted structural samples.
  • The audit scripts used to compute the statistics.
  • Small synthetic repro transcripts, if needed.
  • Exact local counts, versions, and stack traces.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗