Local compaction v2 retains unbounded input_image payloads, causing repeated auto-compaction
What version of Codex is running?
- Codex Desktop:
26.707.72221 - Embedded CLI:
codex-cli 0.144.2 - Platform: macOS 26.3 (Build 25D125), Apple Silicon
- Model:
gpt-5.6-sol
What issue are you seeing?
A long-running, image-heavy Codex Desktop thread enters a repeated auto-compaction cycle. After a compaction completes, the resulting history remains only slightly below the auto-compaction threshold. Even a short new question pushes it over the threshold again, so almost every new turn starts with another compaction.
The compacted replacement_history keeps historical input_image items, including their full inline base64/data-URL payloads. Repeated compactions keep copying the same images into new compacted records.
This produces two related effects:
- The post-compaction prompt remains close to the context threshold, causing immediate re-compaction on subsequent turns.
- The rollout JSONL grows rapidly because the same inline image payloads are persisted repeatedly.
Local evidence
From one affected thread:
| Metric | Observed value |
| --- | ---: |
| Rollout JSONL size | approximately 4.16 GB |
| Compaction records | 224 |
| Images retained by the latest compacted replacement history | 92 |
| Retained inline image/base64 characters | approximately 26.47 million |
| Retained text characters | approximately 188,000 |
| Effective context window reported for the session | 258,400 tokens |
| Default auto-compaction threshold | approximately 244,800 tokens |
| Prompt size immediately after compaction | approximately 236,000-237,000 tokens |
The post-compaction history therefore has only about 8,000 tokens of headroom. A normal follow-up turn is sufficient to trigger compaction again.
No full rollout is attached because it contains private prompts, paths, tool output, and images. I can provide additional redacted structural statistics if needed.
Steps to reproduce
- Use a long-running Codex Desktop thread containing multiple pasted screenshots or image inputs.
- Continue until local/remote-v2 compaction occurs.
- Inspect the newest
type: "compacted"rollout record. - Confirm that
payload.replacement_historyretains user messages containinginput_imagedata URLs. - Send a short follow-up question.
- Observe another automatic compaction even though the previous compaction just completed.
- Repeat several turns and observe the rollout file growing as image payloads are copied into additional compacted records.
Expected behavior
After compaction:
- Retained multimodal history should be bounded by a realistic image/token/byte budget.
- There should be enough hysteresis below the auto-compaction threshold for ordinary follow-up turns.
- Old inline image payloads should not be duplicated indefinitely in every compacted rollout record.
Actual behavior
The current retained-message text budget treats images as zero text tokens and preserves them:
ContentItem::InputImage { .. } => 0,
and later:
ContentItem::InputImage { .. } => truncated_content.push(content_item),
The message-level .max(1) floor limits the number of image-only messages only very weakly. It does not account for image cost inside mixed text/image messages, image count, encoded byte size, or vision-token cost.
Current source:
codex-rs/core/src/compact_remote_v2.rsmessage_text_token_counttruncate_message_text_to_token_budgettruncate_retained_messages_for_remote_compaction
Possible fix direction
For active compacted history:
- Give retained images a conservative estimated token cost, using the existing image-size/detail estimator where possible.
- Add explicit caps for retained image count and/or encoded bytes.
- Keep the newest images first and replace older images with a lightweight placeholder once the image budget is exhausted.
- Add a regression test with many mixed text/image messages verifying that compacted history is bounded and a short next turn does not immediately trigger compaction again.
For rollout persistence, consider storing images as content-addressed blobs or references rather than repeating full base64 strings. That storage concern may be better handled separately under the existing image-heavy rollout issue.
Related issues
- #24388: same underlying retained-
input_imageproblem, closed after the compaction architecture changed; this report reproduces the behavior on the newer local compaction path. - #24550: large inline images in compacted
replacement_historycause Responses WebSocket fallback. - #24676: image-heavy rollout JSONL causes Codex Desktop hangs and difficult session recovery.
- #9601: images can poison context estimation after history mutation.
I am willing to help with additional redacted diagnostics, test-case design, or an implementation if maintainers agree on the approach and invite a PR under the repository contribution policy.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗