Local compaction v2 retains unbounded input_image payloads, causing repeated auto-compaction

Open
#33,493 24 comments 9 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
55/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
rust

Research direction

Start in codex-rs/core/src/compact_remote_v2.rs by reading message_text_token_count, truncate_message_text_to_token_budget, and truncate_retained_messages_for_remote_compaction, then inspect the existing image-size/detail estimator. Add a regression test with mixed text and image messages. Done means retained image history is bounded and a short follow-up does not immediately trigger another compaction.

Written by the indexing model from the issue text.

Description

app bug context
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:

  1. The post-compaction prompt remains close to the context threshold, causing immediate re-compaction on subsequent turns.
  2. 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
  1. Use a long-running Codex Desktop thread containing multiple pasted screenshots or image inputs.
  2. Continue until local/remote-v2 compaction occurs.
  3. Inspect the newest type: "compacted" rollout record.
  4. Confirm that payload.replacement_history retains user messages containing input_image data URLs.
  5. Send a short follow-up question.
  6. Observe another automatic compaction even though the previous compaction just completed.
  7. 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.rs
  • message_text_token_count
  • truncate_message_text_to_token_budget
  • truncate_retained_messages_for_remote_compaction
Possible fix direction

For active compacted history:

  1. Give retained images a conservative estimated token cost, using the existing image-size/detail estimator where possible.
  2. Add explicit caps for retained image count and/or encoded bytes.
  3. Keep the newest images first and replace older images with a lightweight placeholder once the image budget is exhausted.
  4. 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_image problem, closed after the compaction architecture changed; this report reproduces the behavior on the newer local compaction path.
  • #24550: large inline images in compacted replacement_history cause 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.

Dominant language
Rust
Stars
125k
Forks
19.5k
Avg merge
1m
Merged PRs (30d)
1k

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from openai/codex

All issues in openai/codex

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.