memory_stage1 fails on 31% of sessions: "Codex ran out of room in the model's context window"
Nobody has claimed this yet.
- 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-cli0.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 toMEMORY.mdormemory_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:
- Chunk the rollout. Split oversized transcripts into windows, run stage-1 per window, then merge — instead of one all-or-nothing pass.
- 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.
- Degrade instead of dropping. A partial memory built from the first/last N turns is far better than no memory at all.
- 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.
- 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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