Skip to content

... #36806

Description

@KyleBrierley

Environment: Codex Desktop on macOS, CLI 0.146.0, [features] memories = true

Summary

Background memory generation (memory_stage1) submits entire session transcripts to a
model with no size ceiling. On large transcripts this reliably fails with a context-window
error after ingesting the input — consuming quota and producing nothing. Separately, the
shipped defaults allow generation to keep running until only 25% of the plan's quota
remains, and route extraction through whatever model the user selected for interactive
work.

Three distinct problems, in descending order of severity.


1. No per-transcript size cap → repeated context-window failures

memories_1.sqlite on this machine:

memory_stage1   done    165
memory_stage1   error    11

All 11 failures share the same error, with retries exhausted:

last_error:      "Codex ran out of room in the model's context window.
                  Start a new thread or clear earlier history before retrying."
retry_remaining: 0

Failed jobs are dramatically larger than successful ones:

n median mean max
Errored 11 3,450,252 B 13,182,226 B 66,822,293 B
Succeeded 165 492,898 B 1,723,614 B 30,446,821 B

Because retry_remaining reached 0, each of these oversized transcripts was submitted
multiple times, filling a context window and failing on every attempt.

The available settings limit how many rollouts (max_rollouts_per_startup), how
old
they may be (max_rollout_age_days), and how much quota must remain
(min_rate_limit_remaining_percent) — but there is no max_rollout_bytes equivalent. A
single oversized transcript is still submitted whole.

Compounding factor: transcripts are mostly non-text payloads. Composition of the
66.8 MB rollout above, all 111 lines of it:

Payload type items bytes share
image_generation_end 7 19,185,819 28.7%
image_generation_call 7 19,184,741 28.7%
function_call_output 12 16,961,978 25.4%
message 21 11,407,036 17.1%
reasoning / token_count / meta 32 ~67,000 0.1%

57.4% is base64 image data — seven generated images, embedded twice each — submitted
to a pipeline whose output is a few paragraphs of prose. Actual conversation is 17%.

Suggested fix: cap per-transcript input size, chunk extraction, or strip
image_generation_* and function_call_output payloads before submission. Any of the
three would have prevented all 11 failures.


2. min_rate_limit_remaining_percent defaults to 25

Per the config reference,
this defaults to 25. In practice that means background generation continues until the
account is down to its last quarter of quota, then logs:

skipping memories startup because Codex rate limits are below the
configured threshold min_remaining_percent=25

This is the only in-product signal about background memory consumption, and it appears
only once quota is nearly gone. It names no subsystem and suggests no remedy.

On a Pro allowance this threshold is unnoticeable. On Plus it means background work can
claim the majority of the weekly budget before the user opens a session. The behaviour is
working as documented — the concern is that the default is not tier-aware and is not
surfaced anywhere in Settings, only in config.toml.

Suggested fix: scale the default to plan tier, and expose the control in
Settings → Personalization alongside the memories toggle.


3. extract_model is unset by default, inheriting the session model

memories.extract_model and memories.consolidation_model are both optional overrides
with no default. With model = "gpt-5.6-luna" set globally, every background
summarization ran on a frontier model.

A user who selects a frontier model for interactive work is silently opting every
background summarization into frontier pricing, with no indication that the two are
coupled.

Suggested fix: default background extraction and consolidation to a small model.


Scale

Across 176 matched jobs on this machine, memory generation ingested 429,400,860 bytes
of transcript. At a rough 4 bytes/token that is on the order of 100M tokens of input,
none of which appears in any local usage accounting — memory_stage1 jobs record no
tokens_used in state_5.sqlite's threads table and write no session rollout.

(Byte-to-token conversion is an estimate and assumes full ingestion without chunking or
truncation. Treat as order-of-magnitude, not a measured token count. The job counts, byte
counts, and error records above are exact.)

Per-day ingestion during the affected period:

Date Bytes ≈ tokens
2026-07-03 40,379,795 10,094,948
2026-07-22 29,738,749 7,434,687
2026-07-13 23,868,196 5,967,049
2026-07-09 21,497,212 5,374,303
2026-07-18 14,014,570 3,503,642

Why this is hard to diagnose

Because the cost scales with transcript size, the pipeline charges more the more the
product is used — and it does so a day later, in a workload that records no token usage,
writes no rollout, and is attributed in usage analytics to an "Exec" bucket that reads
as user-configured non-interactive invocation.

Reproduction

  1. Enable memories ([features] memories = true).
  2. Run several long sessions, ideally including image generation or large tool output.
  3. Inspect ~/.codex/memories_1.sqlite:
sqlite3 ~/.codex/memories_1.sqlite \
  "select status, count(*), substr(last_error,1,60)
   from jobs where kind='memory_stage1' group by status;"
  1. Cross-reference job_key against the corresponding file size in ~/.codex/sessions/
    to see the relationship between transcript size and failure.

Metadata

Metadata

Assignees

No one assigned

    Labels

    appIssues related to the Codex desktop appbugSomething isn't workingconfigIssues involving config.toml, config keys, config merging, or config updatesmemoryrate-limitsIssues related to rate limits, quotas, and token usage reporting

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions