codex - 💡(How to fix) Fix /goal long-running loop produces 480 KB single log lines via chain-nested turn{} tracing spans (34 GB log in one day)

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Error Message

2026-05-18T17:11:38Z WARN turn{otel.name="session_task.turn" thread.id=<TID> turn.id=AAAA model=gpt-5.5 codex.turn.reasoning_effort=xhigh codex.turn.token_usage.input_tokens=0 codex.turn.token_usage.input_tokens=0 codex.turn.token_usage.cached_input_tokens=0 codex.turn.token_usage.cached_input_tokens=0 ...}

Root Cause

  • #11202 (file_watcher INFO spam) — similar symptom (rapid log growth), different root cause
  • #4345, #4766 (token usage multiplied) — I believe my data provides the mechanism: nested span field duplication
  • #21786 (/goal self-loops with brainstorming) — adjacent area but different layer (product loop vs tracing instrumentation)

Code Example

p50:     359 bytes
p90: 479,776 bytes
p99: 479,910 bytes
max: 481,817 bytes
avg:  56,276 bytes

---

2026-05-18T17:11:38Z  WARN turn{otel.name="session_task.turn" thread.id=<TID> turn.id=AAAA model=gpt-5.5 codex.turn.reasoning_effort=xhigh codex.turn.token_usage.input_tokens=0 codex.turn.token_usage.input_tokens=0 codex.turn.token_usage.cached_input_tokens=0 codex.turn.token_usage.cached_input_tokens=0 ...}
:turn{otel.name="session_task.turn" thread.id=<TID> turn.id=BBBB ... input_tokens=0 input_tokens=0 ...}
:turn{otel.name="session_task.turn" thread.id=<TID> turn.id=CCCC ...}
... (688 more turn spans nested) ...
: codex_core_skills::loader: ignoring interface.icon_large: icon path must not contain '..'

---

$ awk 'length($0) > 100000' ~/.codex/log/codex-tui.log \
  | head -1 \
  | grep -oE 'turn\.id=[a-f0-9-]+' | sort -u | wc -l
691

---

sqlite> SELECT tokens_used FROM threads WHERE id = '<TID>';
1248543402   -- 1.25 billion

sqlite> SELECT tokens_used FROM thread_goals WHERE thread_id = '<TID>';
138610       -- 138K (the truthful value)

---

# Confirm nested turn spans in single line
awk 'length($0) > 100000' ~/.codex/log/codex-tui.log \
  | head -1 | grep -oE 'turn\.id=[a-f0-9-]+' | sort -u | wc -l

# Compare token counters between threads and thread_goals tables
sqlite3 ~/.codex/state_5.sqlite \
  "SELECT t.id, t.tokens_used AS threads_count, g.tokens_used AS goal_count
   FROM threads t JOIN thread_goals g ON g.thread_id = t.id
   WHERE g.status = 'active'"
RAW_BUFFERClick to expand / collapse

Codex version

codex-cli 0.130.0

Plan

ChatGPT Pro

Model

gpt-5.5

Platform

Darwin 25.1.0 arm64 arm (macOS, Apple Silicon)

Terminal

VS Code integrated terminal v1.118.1 (no multiplexer)

Codex doctor report

not available (codex 0.130.0 does not have doctor subcommand yet)


What issue are you seeing?

After running a /goal overnight (status remained active for ~24 hours), my ~/.codex/log/codex-tui.log grew from ~412 MB (8 months of normal usage) to 34 GB in a single day.

1. Single log lines reach 481,817 bytes (~480 KB)

Line length distribution from a 200 MB tail sample:

p50:     359 bytes
p90: 479,776 bytes
p99: 479,910 bytes
max: 481,817 bytes
avg:  56,276 bytes

2. Each monster line contains 691 chain-nested turn{} tracing spans

Truncated example (real content, only IDs anonymized):

2026-05-18T17:11:38Z  WARN turn{otel.name="session_task.turn" thread.id=<TID> turn.id=AAAA model=gpt-5.5 codex.turn.reasoning_effort=xhigh codex.turn.token_usage.input_tokens=0 codex.turn.token_usage.input_tokens=0 codex.turn.token_usage.cached_input_tokens=0 codex.turn.token_usage.cached_input_tokens=0 ...}
:turn{otel.name="session_task.turn" thread.id=<TID> turn.id=BBBB ... input_tokens=0 input_tokens=0 ...}
:turn{otel.name="session_task.turn" thread.id=<TID> turn.id=CCCC ...}
... (688 more turn spans nested) ...
: codex_core_skills::loader: ignoring interface.icon_large: icon path must not contain '..'

Verification:

$ awk 'length($0) > 100000' ~/.codex/log/codex-tui.log \
  | head -1 \
  | grep -oE 'turn\.id=[a-f0-9-]+' | sort -u | wc -l
691

3. Token usage fields duplicated per nesting level

Note the pattern input_tokens=0 input_tokens=0, cached=N cached=N repeated in every span level. This strongly suggests child spans inherit and re-record parent fields without deduplication.

4. Side effect: threads.tokens_used shows impossible value

sqlite> SELECT tokens_used FROM threads WHERE id = '<TID>';
1248543402   -- 1.25 billion

sqlite> SELECT tokens_used FROM thread_goals WHERE thread_id = '<TID>';
138610       -- 138K (the truthful value)

The threads-level counter is inflated ~9000× by cumulative accumulation across nested spans. The goals-level counter (recorded at a different layer) is accurate.

5. Time distribution of the 34 GB log

WindowBytes written
2025-09-26 → 2026-05-17 (8 months)412 MB
2026-05-17 single day1.6 GB
2026-05-18 single day (goal running)30 GB

The 24h of goal execution wrote ~78× the prior 8-month total.

Related issues

  • #11202 (file_watcher INFO spam) — similar symptom (rapid log growth), different root cause
  • #4345, #4766 (token usage multiplied) — I believe my data provides the mechanism: nested span field duplication
  • #21786 (/goal self-loops with brainstorming) — adjacent area but different layer (product loop vs tracing instrumentation)

What steps can reproduce the bug?

  1. Codex CLI 0.130.0 with [features] goals = true in ~/.codex/config.toml (default)
  2. Start /goal with an open-ended self-iterating objective such as "keep iterating, don't stop until you've polished every aspect, I'll check tomorrow morning"
  3. Let it run unattended for several hundred turns (mine reached 691)
  4. Observe ~/.codex/log/codex-tui.log growing rapidly (~30 GB / 24h in my case)

Diagnostics:

# Confirm nested turn spans in single line
awk 'length($0) > 100000' ~/.codex/log/codex-tui.log \
  | head -1 | grep -oE 'turn\.id=[a-f0-9-]+' | sort -u | wc -l

# Compare token counters between threads and thread_goals tables
sqlite3 ~/.codex/state_5.sqlite \
  "SELECT t.id, t.tokens_used AS threads_count, g.tokens_used AS goal_count
   FROM threads t JOIN thread_goals g ON g.thread_id = t.id
   WHERE g.status = 'active'"

Thread id available on request (omitted from public issue for privacy).


What is the expected behavior?

Each turn span should be a sibling under the goal span, not a chained child of the prior turn. Specifically:

  • turn spans must be dropped at the end of each iteration so subsequent turns start at the same depth
  • Fields recorded on a child span should not duplicate into parent span output
  • Long-running /goal sessions should not accumulate unbounded tracing depth

Likely culprits in goal_loop instrumentation:

  • Span::enter() guard stored in a long-lived struct, never dropped between iterations
  • #[instrument] on a function that recursively self-calls (forming parent→child chain instead of siblings)
  • Span context leak across tokio::spawn boundaries without Instrument::in_current_span or Span::none()

Either fix would also resolve the inflated threads.tokens_used counter, which appears to be an artifact of the same nesting bug.


Additional information

  • Active goal had token_budget = 32,507,871 and real tokens_used = 138,610 (0.4% consumed). The 1.25B figure is purely a span-nesting artifact, not real consumption
  • 691 distinct turn.id UUIDs confirmed via grep — these are real turn iterations, not display artifacts
  • Pre-2026-05 logs in the same file don't exhibit this issue because turns numbered in tens, not hundreds. Hundreds of turns appears to be the threshold where the bug becomes catastrophic (quadratic data amplification: N turns × N field re-records per log line)
  • After : > ~/.codex/log/codex-tui.log, Codex continued writing normally — no functional impact beyond disk space
  • I'm happy to provide a sanitized excerpt of the actual 480 KB log line if it would help; please ask

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

codex - 💡(How to fix) Fix /goal long-running loop produces 480 KB single log lines via chain-nested turn{} tracing spans (34 GB log in one day)