openai / openai/codex

memory_stage1 fails on 31% of sessions: "Codex ran out of room in the model's context window"

Open
#38,860 7 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug CLI context memory
Dominant language
Rust
Stars
125k
Forks
19.5k
PR merge metrics
PR metrics pending

Description

Summary

Background memory generation (memory_stage1) permanently fails on ~31% of sessions with Codex ran out of room in the model's context window. The job feeds an entire rollout into the model in one shot with no chunking, truncation, or fallback, so any session whose transcript exceeds the context window is silently dropped from long-term memory forever.

On my machine 93 sessions have exhausted all retries and will never be consolidated. Nothing surfaces this to the user — the memory system simply has holes in it.

Environment

  • codex-cli 0.144.1
  • macOS 26.3 (Apple Silicon)
  • Memory enabled: [memories] generate_memories = true, use_memories = true

Evidence

All figures below come from $CODEX_HOME/memories_1.sqlite on a single machine covering 2026-05-31 → 2026-08-12.

Job outcomes:

kind status count
memory_stage1 done 214
memory_stage1 error 95
memory_consolidate_global done 1

That is a 30.7% failure rate.

Error breakdown (select substr(last_error,1,120), count(*) from jobs where status='error' group by 1):

last_error count
Codex ran out of room in the model's context window. Start a new thread or clear earlier history before retrying. 92
request timed out 3

So 97% of all failures are the same context-overflow error.

Correlation with rollout size. Matching each job_key to its rollout-*.jsonl:

failed jobs (n=92 matched) successful jobs (n=179 matched)
median rollout size 13.6 MB 1.3 MB
mean 36.3 MB 12.9 MB
max 412.7 MB 446.7 MB

Failed sessions are ~10× larger at the median. Note the maxima: a 446.7 MB rollout succeeded while a 412.7 MB one failed, so raw file size is a strong correlate but not the actual trigger — what matters is how much of the transcript ends up in the prompt. There is no size guard either way.

Retries do not help. Of the 95 failures, 93 have retry_remaining = 0 — the system has permanently given up. The remaining 2 have retries left but their retry_at elapsed weeks ago and their source rollouts no longer exist.

Not a transient regression. Failures are continuous from 2026-05-31 to 2026-08-12 with no improving trend.

Impact

  • 93 of 95 failed sessions have no row at all in stage1_outputs — those sessions contributed nothing to MEMORY.md or memory_summary.md.
  • The user is never told. There is no warning, no log surfaced in the TUI, and no indication that memory coverage is incomplete.
  • Retrying is impossible by design: the job has already burned its retry budget, and the failure mode is deterministic — re-running the same oversized rollout through the same path will always fail.
  • This disproportionately drops the most substantial sessions. Long, multi-hour working sessions are exactly the ones most worth remembering, and they are the ones guaranteed to fail.

How to verify on your own machine

cp "$CODEX_HOME/memories_1.sqlite" /tmp/m.sqlite
sqlite3 /tmp/m.sqlite \
  "select status, count(*) from jobs where kind='memory_stage1' group by 1;"
sqlite3 /tmp/m.sqlite \
  "select substr(last_error,1,120), count(*) from jobs
   where status='error' group by 1 order by 2 desc;"

(Copy first — sqlite3 -readonly fails against the live DB because of the WAL sidecar.)

Suggested fixes

Roughly in order of effort:

  1. Chunk the rollout. Split oversized transcripts into windows, run stage-1 per window, then merge — instead of one all-or-nothing pass.
  2. Pre-flight token estimate. Measure the prompt before dispatching; if it exceeds the window, degrade to a truncated or sampled pass rather than erroring out.
  3. Degrade instead of dropping. A partial memory built from the first/last N turns is far better than no memory at all.
  4. Do not consume the retry budget on a deterministic failure. Context overflow will never succeed on retry with an unchanged input; either fix the input or mark it needs-different-strategy so a future version can pick it up.
  5. Surface it. Expose failed consolidations somewhere the user can see, so silent gaps in memory are at least knowable.

Happy to run additional queries against my local DB if that would help narrow it down.

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.

Research direction

Start by tracing the memory_stage1 background job and its jobs, stage1_outputs, and memories_1.sqlite records. Reproduce an oversized rollout and inspect how context-overflow errors consume retries and leave sessions without output. Done means oversized sessions receive a defined fallback or are surfaced for later handling instead of being silently lost.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust, sqlite
Domain
backend, databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.