Skip to content

Shell snapshot logs false ENOENT on temp cleanup after thread/start #17549

@m-mohamed

Description

@m-mohamed

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:

  • initialize alone is quiet
  • direct thread/start reproduces it consistently for me
  • direct thread/resume also 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}.sh file 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:

  • initialize without thread/start produced no shell snapshot warning
  • the thread/start repro above produced one shell snapshot warning on each of 3 consecutive runs
  • thread/resume reproduced 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:

  1. build final path
  2. build temp path
  3. write and validate the temp snapshot
  4. rename temp to final path
  5. return a new ShellSnapshot bound to the final path
  6. drop the old temp holder, whose Drop unconditionally removes self.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-1903
  • codex-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:

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingtool-callsIssues related to tool calling

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions