codex exec resume accepts nonexistent session ids and starts a new thread instead of failing

Resolved 💬 3 comments Opened Mar 23, 2026 by aquiles-ai123 Closed Apr 6, 2026
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

codex exec resume accepts a nonexistent session id and starts a new thread instead of failing

Summary

If I pass a UUID that does not correspond to any existing session into codex exec resume, Codex does not return a "not found" style error.

Instead, it starts a brand-new thread, runs the prompt normally, and exits 0.

That makes resume unsafe for automation because a typo or stale id can silently create a fresh session instead of failing loudly.

Repro

Use a UUID that does not exist:

codex exec resume 00000000-0000-0000-0000-000000000000 --json --skip-git-repo-check \
  "Reply with the single word ghost and stop." \
  > /tmp/codex_resume_nonexistent_probe.jsonl
printf "outer_exit=%s\n" "$?"

Observed transcript:

{"type":"thread.started","thread_id":"019d1c0b-6504-7b32-8ac6-74d98b92a141"}
{"type":"item.completed","item":{"id":"item_0","type":"agent_message","text":"ghost"}}

Observed shell exit:

outer_exit=0

The thread_id in the transcript is not the requested UUID. Codex silently started a fresh thread instead of reporting that the requested session id does not exist.

Control

A real session id does resume correctly.

Create a normal session:

codex exec --skip-git-repo-check --color never --json -C /home/cryptotrading74 \
  "Reply with the single word zebra and stop." \
  > /tmp/codex_resume_control_seed.jsonl

Observed thread:

{"type":"thread.started","thread_id":"019d1c0a-0137-73f3-bf4a-88c90739150c"}

Resume it:

codex exec resume 019d1c0a-0137-73f3-bf4a-88c90739150c --json --skip-git-repo-check \
  "What was your previous one-word reply in this session? Answer with just that word." \
  > /tmp/codex_resume_control_check.jsonl

Observed transcript:

{"type":"thread.started","thread_id":"019d1c0a-0137-73f3-bf4a-88c90739150c"}
{"type":"item.completed","item":{"id":"item_0","type":"agent_message","text":"zebra"}}

So the broken behavior is not "resume always creates a new thread"; it happens specifically when the requested id is missing.

Expected behavior

If the requested session id does not exist, codex exec resume should fail clearly with a nonzero exit code and a "session not found" style message.

Actual behavior

codex exec resume accepts the nonexistent id, creates a new thread, completes the turn, and exits 0.

Why this matters

This is dangerous for scripts and operators because a stale or mistyped resume id can look successful while actually starting a fresh conversation.

Related

I also reproduced the same symptom with an ephemeral exec session id in #15538. That appears to be a specific instance of the more general "missing session id silently creates a new thread" behavior.

Files / artifacts

  • /tmp/codex_resume_nonexistent_probe.jsonl
  • /tmp/codex_resume_control_seed.jsonl
  • /tmp/codex_resume_control_check.jsonl

View original on GitHub ↗

3 Comments

github-actions[bot] contributor · 5 months ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #15538

Powered by Codex Action

middleDuckAi · 5 months ago

Repro

  • Reproduced the explicit-resume fallback problem on current main.
  • This same failure path covers both #15538 and #15539: explicit codex exec resume <id> was silently starting a new thread when the requested target was missing.

Root Cause

  • Explicit resume ids were sharing the same fallback path as resume --last.
  • I prepared one scoped fix that makes explicit missing targets fail with Session not found: <id> while leaving resume --last behavior unchanged.

Validation

  • cargo fmt --all
  • cargo test -p codex-exec resolve_resume_target
  • cargo test -p codex-exec exec_resume_by_missing_id_fails_without_starting_new_session
  • cargo test -p codex-exec exec_resume_by_ephemeral_id_fails_without_starting_new_session

Risk

  • Low. The change is intentionally scoped to explicit resume targets and leaves the resume --last path alone.

Maintainer Pickup

gh pr create --repo openai/codex --base main --head middleDuckAi:middleDuck/codex-15538-15539-resume-missing-session --title "$(gh pr view 3 --repo middleDuckAi/codex --json title --jq .title)" --body "$(gh pr view 3 --repo middleDuckAi/codex --json body --jq .body)"
etraut-openai contributor · 4 months ago

Thanks for the bug report. This has recently been fixed.