Hook-injected <hook_prompt> messages cause infinite loop, consuming billions of tokens with zero useful output

Open 💬 4 comments Opened Jul 21, 2026 by xiaofuCoding-stack

What version of Codex CLI is running?

codex-cli 0.144.5

What subscription do you have?

Pro

Which model were you using?

gpt-5.5

What platform is your computer?

Darwin 25.5.0 arm64 arm

What terminal emulator and version are you using (if applicable)?

iTerm2 3.6.11

Codex doctor report

What issue are you seeing?

What issue are you seeing?

An external hook (registered in ~/.codex/hooks.json) that returns a <hook_prompt> message can cause an infinite loop where Codex keeps sending requests to the model with zero useful output, consuming billions of tokens.

In my case, a third-party "OMX" stop hook was registered. When the model finished a turn, the stop hook fired and injected a <hook_prompt> message into the conversation: "OMX cannot authorize Stop for unmatched session id ...". Codex treated
this hook output as a new user message and sent it back to the model. The model responded with a short acknowledgment. That response triggered the stop hook again, which injected another identical <hook_prompt> message — creating an infinite
loop.

Key metrics from the affected session (thread 019f7d3e-4dd2-77f0-b96d-83ad5778370e):

  • Total tokens consumed: 343,651,633 (~3.44 billion)
  • Duration: ~9 hours (02:38 UTC to 10:52 UTC, 2026-07-20)
  • Total model requests: 1,843 — of which 1,789 (99.2%) were hook-injected messages, only 14 were real user messages
  • 97% of requests produced output < 100 tokens — the model just repeated the same acknowledgment each time
  • Each request grew the context window by ~8,000 input tokens as the conversation history kept expanding
  • Context compaction occurred 6 times but did not break the loop
  • The loop continued for ~9 hours until the weekly token quota was exhausted

What steps can reproduce the bug?

  1. Register an external hook in ~/.codex/hooks.json that fires on stop events and returns a <hook_prompt> message (e.g., a hook that cannot match the current session and returns an error message)
  2. Start a Codex session with any prompt
  3. After the model responds, the stop hook fires and injects its message
  4. Codex treats the hook output as a new user input → model responds → stop hook fires again → infinite loop

Thread ID: 019f7d3e-4dd2-77f0-b96d-83ad5778370e

What is the expected behavior?

Hook-injected messages should not automatically trigger new model requests in a loop. At minimum:

  1. Hook output should not be treated as new user input — messages from hooks should be informational only and not cause a new model turn
  2. Add a maximum auto-turn limit — if N consecutive turns have no real user input, the session should pause or stop
  3. Add debouncing/rate-limiting — identical hook messages within a short window should be suppressed

Without any of these safeguards, a misconfigured or incompatible hook can silently drain an entire weekly token quota with zero useful output.

Additional information

The same pattern also affected a second session (thread 019f5ecb-8ea4-73c0-a225-9ead151f6a78, 3.14 billion tokens) that was created on 2026-07-14 and continued running on 2026-07-20. The combined token waste from just these two sessions exceeded
6.5 billion tokens.

Workaround: Removing the offending hook from ~/.codex/hooks.json and the related entries from ~/.codex/config.toml stops the issue from recurring.

View original on GitHub ↗

4 Comments

xiedongqingxiao-ops · 26 days ago

I can corroborate a closely matching failure mode on Codex Desktop for Windows.

Environment:

  • OpenAI Codex Desktop: 26.727.6591.0 (x64 MSIX)
  • Windows: 10.0.26200.8875
  • The affected workspace had managed SessionStart/compact and Stop hooks, plus a recently added local supervision harness.

Observed on 2026-08-01 through 2026-08-02:

  • During a large implementation task, the agent repeatedly re-entered meta-workflow stages (problem contract -> freeze -> review -> freeze) instead of producing implementation artifacts.
  • Compaction/continuation did not break the cycle.
  • The behavior recurred after opening a fresh task.
  • A local postmortem estimated more than 500 million tokens were consumed across the affected runs. I have not independently reconstructed the exact count yet, so this number should be treated as an estimate.
  • The practical outcome was near-zero useful output despite prolonged unattended execution and repeated model/tool activity.

This symptom strongly matches the hook-triggered auto-turn loop described here, especially because Stop/compact hooks were active. I have not yet proved that the same hook message was the sole causal trigger on this Windows installation, so I am adding this as corroborating evidence rather than claiming an identical root cause.

The workspace also had a large instruction/skill stack. That may have amplified per-turn context cost, but it should not permit an unbounded sequence of model turns without new human input.

Safeguards that would have prevented the incident:

  1. A hard maximum on consecutive automatic turns without real user input.
  2. Deduplication/rate limiting for identical hook-generated messages.
  3. Hook output should not automatically count as a fresh user turn.
  4. A visible auto-turn counter and emergency stop when repeated turns produce no file diff, test result, or other progress signal.

I am not attaching session transcripts because they contain private project material. I can provide redacted event counts or specific log fields if maintainers identify what would be most useful.

xiedongqingxiao-ops · 26 days ago

Incident impact addendum (Windows reproduction)

The original corroborating comment omitted the most important severity data. User-observed impact on 2026-08-01 was:

  • Approximately 80% of the account's weekly Codex allowance was consumed by the incident.
  • The first failed run consumed about 60% of the weekly allowance.
  • A restarted/resumed review run consumed roughly another 20%.
  • A local postmortem estimated more than 500,000,000 tokens across the affected runs. This remains an estimate because the raw session count has not been independently reconstructed.
  • At least one runaway segment was manually stopped after approximately 35 minutes when no new artifact or useful progress appeared.
  • Useful implementation output: zero planned features completed.
  • Even the smallest initial requested behavior (a continuation/summary instruction) did not become functional.
  • A temporary local supervision harness was added in an attempt to stop the behavior, but it also produced no usable recovery output.
  • A downstream project blocked on this implementation had to be moved to a separate web workflow because the remaining weekly allowance could not support continued recovery attempts.

These figures are user-visible quota and outcome records, not inferred cost projections. Raw transcripts are not attached because they contain private project material.

xiedongqingxiao-ops · 26 days ago

Exact rollout reconstruction (replaces prior >500M estimate)

I reconstructed the affected local rollout families using each file's final payload.info.total_token_usage.total_tokens and the child parent_thread_id graph:

  • Initial ARCH root 019fbc65-...: 11 sessions, 420,775,426 tokens
  • Reopened ARCH root 019fbd87-...: 5 sessions, 61,684,846 tokens
  • Harness/recovery roots: 76,001,247 tokens
  • Original incident total: 558,461,802 tokens
  • Later failed ARCH-F1 reattempt: 25,544,534 tokens
  • Cumulative affected/recovery total: 584,006,336 tokens

The original incident corresponds to the user-observed loss of approximately 80% of the weekly allowance (about 60% in the first run and another 20% after reopening). The previous ">500M" statement can now be treated as confirmed and refined to the exact local rollout total above.

xiedongqingxiao-ops · 26 days ago

Arithmetic correction

The exact reconstruction comment above contains one subtotal typo: recovery/harness task families total 76,001,530 tokens, not 76,001,247. The already reported original incident total (558,461,802) and cumulative total including the later failed reattempt (584,006,336) are unchanged.