app-server thread/resume rejects equivalent symlinked rollout paths as stale
What issue are you seeing?
When using the experimental app-server API as a third-party client, thread/resume can reject a running thread if the requested rollout path and the active rollout path refer to the same file through different symlink spellings.
The failure happens in the running-thread resume path when params.path is provided. The current check compares the two PathBuf values literally:
requested_path != active_path
On machines where the home directory is a symlink, one path can use the symlinked home while the other uses the resolved real path. These paths point to the same rollout JSONL, but app-server treats them as different and returns:
cannot resume running thread <thread-id> with stale path: requested `<symlink-home>/.../rollout-<id>.jsonl`, active `<real-home>/.../rollout-<id>.jsonl`
This blocks third-party clients that rely on experimental thread/resume with path.
What steps can reproduce the bug?
- Run Codex app-server with experimental API enabled.
- Use an environment where the user home directory is a symlink, for example:
/home/userresolves to/mnt/users/user- or
/Users/userresolves through another mounted path
- Start or resume a thread so app-server has a running thread with an active rollout path.
- Call
thread/resumefor that same running thread withparams.pathset to the rollout JSONL path using the symlinked home spelling. - Observe that app-server compares the requested path and active rollout path literally and rejects the request as
stale path, even though both paths resolve to the same file.
A downstream workaround was to temporarily disable this stale-path check, but the proper upstream fix should preserve the stale-path protection while comparing normalized/canonicalized paths, or otherwise using a path identity check that treats equivalent symlinked paths as the same file.
What is the expected behavior?
thread/resume should allow resuming a running thread when params.path and the active rollout path resolve to the same file.
It should still reject genuinely stale paths that point to a different rollout/thread.
Additional information
This appears related to the broader class of path identity issues reported in #18483, #20317, and #20882, but the trigger here is narrower: the app-server v2 experimental thread/resume running-thread path check rejects equivalent symlinked paths before the client can resume.
Environment observed downstream:
- Codex CLI/app-server version:
0.130.0 - Platform:
Darwin 24.6.0 arm64 arm - Scenario: third-party app-server client, experimental API enabled
- Home directory is symlinked on internal remote machines
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗