Desktop compaction repeatedly embeds full image base64 in compacted checkpoints

Open 💬 5 comments Opened May 18, 2026 by SimpleZion

What version of the Codex App are you using?

Codex Desktop on Windows:

  • App package: OpenAI.Codex
  • Version: 26.513.4821.0
  • Package: OpenAI.Codex_26.513.4821.0_x64__2p2nqsd0c76g0

One affected rollout also recorded cli_version: 0.119.0-alpha.28.

What platform is your computer?

Windows x64.

What issue are you seeing?

Codex Desktop context compaction appears to repeatedly persist full inline image payloads inside compacted checkpoints, especially under payload.replacement_history.

This makes long image-heavy threads keep growing even after automatic compaction. It also keeps the "background information window" / context usage high after compaction because the new compacted checkpoint can still contain the previous screenshots as base64 data.

This looks related to #18629 and #22603, but this report is focused on the compaction layer: old compacted checkpoints and the latest compacted.payload.replacement_history repeatedly contain full image payloads instead of deduplicated references, lightweight placeholders, or a single latest compacted state.

Local evidence

I inspected local saved session JSONL files under the Codex home directory. I am intentionally omitting raw session contents, local paths, screenshots, cookies, thread text, and user data.

Affected thread A

Before repair:

  • Rollout JSONL size: 904.9 MB
  • JSONL records: 40,378
  • compacted records: 128
  • Total bytes in compacted records: 770.9 MB
  • Lines containing data:image: 315
  • Total bytes in lines containing data:image: 822.5 MB
  • Total data:image references: 1,787
  • Latest compacted record size: 7.66 MB
  • Latest compacted image refs: 15
  • Latest compacted.payload.replacement_history length: 185
  • Latest compacted visible string chars before image removal: about 7,954,167
  • Latest compacted contained 15 image parts, plus a copied developer/plugin instruction block and an encrypted compaction blob.

After a local schema-aware cleanup that kept the latest compacted checkpoint but removed inline image payloads and old duplicate compacted checkpoints:

  • compacted records: 1
  • data:image refs: 0
  • Latest compacted size: about 316 KB
  • Latest replacement_history length remained 185
  • Latest visible string chars after image removal: about 264,828

This is the important signal: the useful compacted text was much smaller than the full checkpoint because prior screenshots had been embedded into replacement_history.

Affected thread B

Another long thread repeatedly regenerated large compacted checkpoints:

  • One snapshot: rollout size 430 MB
  • compacted records: 14
  • Total bytes in compacted records: 117.6 MB
  • Latest compacted record: 9.02 MB
  • Latest compacted image refs: 24
  • The Codex UI showed the background information window still around 54% / 139k tokens after compaction.
  • Local token-count records around the same time showed a post-compaction context total around 138,789 / 258,400.

After removing old compacted records and image payloads from the latest compacted checkpoint, the same thread became much smaller and the latest compacted record was under 100 KB. However, if the thread continued running, Codex could generate new compacted records that reintroduced the same image payloads.

Why this is a product-level problem

Users can manually edit JSONL as a workaround, but it is risky. During local recovery, replacing large base64-looking strings too broadly can damage fields such as encrypted_content, which then causes resume/reconnect failures like:

{
  "type": "error",
  "error": {
    "type": "invalid_request_error",
    "code": "invalid_encrypted_content",
    "message": "The encrypted content [...] could not be verified. Reason: Encrypted content could not be decrypted or parsed."
  },
  "status": 400
}

So the durable fix should not require users to manually mutate saved session JSONL. Codex should compact or repair these sessions in a schema-aware way.

Steps to reproduce

  1. Use Codex Desktop in a long-running thread.
  2. Use image-producing workflows repeatedly, such as screenshots, browser/computer-use images, image attachments, or other tool outputs that produce input_image / data:image/...;base64,... payloads.
  3. Let Codex automatically compact the context several times.
  4. Inspect the saved rollout JSONL.
  5. Observe many compacted records and a latest compacted.payload.replacement_history that still contains full image payloads.
  6. Continue the same thread; observe that automatic compaction can create more large compacted records rather than converging to a lightweight latest summary.

Expected behavior

Context compaction should not repeatedly embed full image bytes in compacted.payload.replacement_history.

Instead, Codex should:

  • store image blobs out-of-line and keep only lightweight references in replayable history
  • deduplicate image payloads across records and compacted checkpoints
  • avoid retaining old compacted checkpoints once a newer compacted checkpoint supersedes them, or keep them out of the replay/hydration path
  • replace old image-heavy tool outputs with schema-valid lightweight placeholders during compaction
  • keep encrypted_content opaque or remove whole reasoning records in a schema-aware way during any repair path
  • provide a built-in "repair / strip old media payloads" action for already affected sessions

Actual behavior

compacted checkpoints can contain full inline image base64 payloads. Old compacted checkpoints accumulate, and the latest compacted checkpoint can still contain many prior screenshots in replacement_history. The thread remains slow/heavy after compaction and can continue to re-grow as new compacted checkpoints are written.

Related issues

  • #18629
  • #22603
  • #11845

Privacy note

I am not attaching the raw rollout JSONL because it contains private prompts, local paths, screenshots, and authentication material. The report above includes only sanitized structural measurements and field/type counts.

View original on GitHub ↗

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