Shell snapshot logs false ENOENT on temp cleanup after thread/start
What version of Codex CLI is running?
codex-cli 0.120.0
What subscription do you have?
ChatGPT Pro
Which model were you using?
Not applicable. The warning is emitted during app-server thread startup before any turn execution.
What platform is your computer?
Darwin 25.3.0 arm64 arm
What terminal emulator and version are you using (if applicable)?
N/A for the minimal repro. It uses raw stdio codex app-server from a normal zsh shell on macOS, without an editor-specific client involved.
What issue are you seeing?
Fresh app-server thread startup can emit a shell snapshot cleanup warning even though snapshot creation appears to have succeeded.
Observed warning:
2026-04-12T17:45:47.295243Z WARN codex_core::shell_snapshot: Failed to delete shell snapshot at "/Users/<redacted>/.codex/shell_snapshots/019d82cc-b457-79a1-82fd-2f85ba435611.tmp-1776015946895804000": Os { code: 2, kind: NotFound, message: "No such file or directory" }
This looks like false-positive warning noise rather than a functional failure:
initializealone is quiet- direct
thread/startreproduces it consistently for me - direct
thread/resumealso reproduces it on multiple unrelated stored threads - the warning path uses the temp snapshot filename form
{thread_id}.tmp-{nonce} - in a timed run, the finalized
{thread_id}.{nonce}.shfile appeared when the temp-path warning was logged
What steps can reproduce the bug?
This direct repro triggers it consistently for me on 0.120.0:
import json
import subprocess
import time
proc = subprocess.Popen(
["codex", "app-server"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
)
def send(msg):
proc.stdin.write(json.dumps(msg) + "\n")
proc.stdin.flush()
send({
"id": 1,
"method": "initialize",
"params": {
"clientInfo": {"name": "simple-start-repro", "version": "0"},
"capabilities": {"experimentalApi": False, "optOutNotificationMethods": []},
},
})
send({"method": "initialized"})
send({
"id": 2,
"method": "thread/start",
"params": {
"cwd": "/tmp/codex-shell-snapshot-repro",
"ephemeral": True,
"approvalPolicy": "on-failure",
},
})
time.sleep(5)
proc.terminate()
stdout, stderr = proc.communicate(timeout=3)
print(stderr)
Observed stderr:
2026-04-12T17:45:47.295243Z WARN codex_core::shell_snapshot: Failed to delete shell snapshot at "/Users/<redacted>/.codex/shell_snapshots/019d82cc-b457-79a1-82fd-2f85ba435611.tmp-1776015946895804000": Os { code: 2, kind: NotFound, message: "No such file or directory" }
Sanity checks I ran locally:
initializewithoutthread/startproduced no shell snapshot warning- the
thread/startrepro above produced one shell snapshot warning on each of 3 consecutive runs thread/resumereproduced the same warning on multiple unrelated stored threads, so this does not look thread-specific
What is the expected behavior?
After successful shell snapshot creation, Codex should not warn that it failed to delete the old temp snapshot path.
Additional information
Current main in codex-rs/core/src/shell_snapshot.rs appears to do:
- build final path
- build temp path
- write and validate the temp snapshot
- rename temp to final path
- return a new
ShellSnapshotbound to the final path - drop the old temp holder, whose
Dropunconditionally removesself.path
If that reading is correct, the warning is caused by dropping an object that still owns the pre-rename temp path.
Relevant current-source references:
codex-rs/core/src/codex.rs:1890-1903codex-rs/core/src/shell_snapshot.rs:127-190
I also found a likely test gap here. Existing shell snapshot tests cover create/delete behavior, but I do not see one that asserts successful temp-to-final promotion does not trigger a spurious temp-path cleanup warning:
codex-rs/core/src/shell_snapshot_tests.rs:189-244
I searched existing issues first and found related shell snapshot reports, but not one that looked like this exact temp-path ENOENT after successful promotion. The closest related ones I found were:
- #10883
- #14824
- #16070
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗