Skip to content

app-server thread/resume rejects equivalent symlinked rollout paths as stale #21898

@SDGLBL

Description

@SDGLBL

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?

  1. Run Codex app-server with experimental API enabled.
  2. Use an environment where the user home directory is a symlink, for example:
    • /home/user resolves to /mnt/users/user
    • or /Users/user resolves through another mounted path
  3. Start or resume a thread so app-server has a running thread with an active rollout path.
  4. Call thread/resume for that same running thread with params.path set to the rollout JSONL path using the symlinked home spelling.
  5. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    app-serverIssues involving app server protocol or interfacesbugSomething isn't working

    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