Codex Desktop Remote SSH: thread-management RPCs hang indefinitely while app-server stays healthy
What version of the Codex App are you using?
- Codex Desktop controlling a saved SSH project
- Remote session metadata:
codex-cli 0.146.0 - Desktop build was not present in the remote rollout metadata
- Incident date: 2026-07-31 UTC
What subscription do you have?
ChatGPT Pro.
What platform is your computer?
Sanitized topology:
- Codex Desktop host: Windows
- Saved project and parent/controller task: remote Linux host over SSH
- Target: an existing Git repository and a dedicated worktree on the remote host
- Repository, project, branch, host, username, task, and prompt identifiers are omitted
Severity / requested priority
High impact — please prioritize for focused triage.
This is not only a sidebar grouping defect. It is a compound fail-open chain in which several individually reported failure modes combine:
- official Desktop thread-management calls stop returning;
- no structured timeout or project-creation error is delivered;
- the agent changes the semantic target from
projecttoprojectless, despite an explicit tool contract forbidding that for repository work; - project identity is lost by construction;
- projectless routing loses SSH host affinity and can place the repository task on the local Windows computer;
- the task may then lack the requested checkout, dependencies, credentials, security policy, and filesystem while still appearing to be a valid delegated task.
In this incident, a wrong-host task was noticed and stopped before mutation. Without that external observation, the same chain could cause work to run against or write to the wrong machine or checkout.
What issue are you seeing?
An interactive Codex Desktop controller was running in a valid saved SSH Git project and needed to create a separate project task in a worktree.
Project discovery completed normally in 0.4 seconds and returned:
- the expected saved remote project;
- the expected Linux path and SSH host;
isGitRepository: true.
The first project-scoped creation request then remained pending until it was manually terminated. Two further project-scoped attempts behaved the same way, including one using a freshly created branch at an exact known commit.
The incident was not limited to project/worktree initialization. Read-only task listing and projectless creation also stopped returning. Later, task read and cross-task message calls were affected as well.
After the thread-tool path recovered, the agent silently substituted a projectless target for the repository task and described it to the user as merely bypassing the project workspace initialization layer. The resulting task had no project association in the Desktop UI.
A later independent reproduction from the same SSH controller made the host-affinity failure explicit:
- projectless creation returned
hostId: localand a Windows output directory; - the task could not access the requested Linux worktree;
- recreating the task with a saved remote project target returned in 1.1 seconds on the expected SSH host.
Captured operation timeline
All identifiers and absolute paths have been removed.
| Operation | Attempts | Observed result |
|---|---:|---|
| Project discovery | 1 | Completed in 0.4s with the correct saved SSH Git project |
| create_thread(target=project) | 3 | No result; manually terminated after 228.9s, 230.0s, and 467.7s |
| create_thread(target=projectless) | 3 | No result; manually terminated after 177.5s, 188.4s, and 208.6s |
| list_threads | 2 | No result; manually terminated after 70.3s and 141.0s |
| Later read_thread / send_message_to_thread | multiple | Intermittently stopped returning |
| Later projectless creation | 1 | Completed, but without project association |
| Independent projectless control | 1 | Completed on local Windows host instead of parent SSH host |
| Project-scoped retry | 1 | Completed in 1.1s on the expected SSH host |
During the pending calls, the tool returned no:
- structured error;
- timeout object;
- rejected project ID;
pendingWorktreeId;- canonical task ID;
- overload response.
The calls simply remained pending until the outer execution cell was terminated.
The unsafe semantic fallback
The agent-visible tool contract said:
Use project for local or remote repository work, projectless for work without a repository.
It also described creation as non-blocking and stated that a ready task returns a task and host identity while setup in progress may return a pending-worktree identity.
Despite that contract, after the project calls did not return, the agent explicitly changed the target to:
{
"target": {
"type": "projectless",
"directoryName": "<sanitized>"
}
}
The agent told the user this was still equivalent to a new task and independent worktree and only bypassed the failed project initialization layer. That statement was incorrect:
projectIdwas omitted;- the new task was not a member of the saved project;
- project instructions and project identity were not preserved;
- host selection was no longer tied to the saved SSH project;
- a later projectless task landed on the local Windows host.
Controls that rule out the repository and local Git environment
The following remained healthy during the failure window:
- The saved project was discoverable with the correct SSH host and Git-repository flag.
- The requested branch could be created immediately at the expected commit.
- A manual
git worktree addcompleted in approximately 0.3 seconds. - Other app-server task creation and local task persistence continued working.
- The remote app-server process remained alive; there was no correlated crash or restart.
- Configured MCP/plugin clients initialized in approximately one second.
- There was no required MCP initialization failure.
- The same Desktop thread-tool path failed for project creation, projectless creation, and read-only listing.
This rules out a missing project, invalid project ID, occupied branch, broken Git checkout, general filesystem failure, total app-server outage, and the known pattern where an unhealthy required MCP blocks every new thread/start.
The narrowest evidence-supported boundary is the Desktop codex_app thread-management bridge: handler dispatch, route ownership, callback/response delivery, or its remote control channel. The exact internal mechanism is not proven from public/local evidence.
Expected behavior
- A project-scoped task creation request must return promptly with a ready identity, a pending-worktree identity, or a structured actionable error.
- Pending tool calls must have bounded timeouts and preserve whether a side effect may have occurred.
- A failed or timed-out project target must never be silently replaced with
projectless. - Repository work should fail closed or require explicit user confirmation before changing target semantics.
- Projectless creation from a remote executor should inherit the executor host, require an explicit destination host, or fail closed.
- Creation results should always expose the actual destination host, project association, and canonical task identity.
- A wrong-host or no-project destination should be detected before the child begins work.
- Retrying a side-effecting creation request should be idempotent and must not create duplicate tasks.
Actual behavior
- The valid project target did not return a result or error.
- Multiple unrelated thread-management methods shared the same non-returning behavior.
- The agent treated a different target type as a safe retry.
- The resulting task lost its project association.
- A later projectless repository task was routed from the SSH controller to local Windows.
- Only external observation prevented a possible wrong-machine mutation.
Why this is more severe than the individual related reports
Each related report covers one part of the chain, but this incident captures the end-to-end composition:
valid saved SSH project
-> thread-management handler/response path stops returning
-> no bounded error or trustworthy side-effect state
-> agent violates target contract and retries as projectless
-> project identity disappears
-> SSH host affinity disappears
-> repository task can run on the local desktop host
The failure therefore crosses API liveness, side-effect safety, agent contract compliance, project identity, and remote host routing. Fixing only the sidebar display would not address the unsafe execution path.
Related public reports
- #35030 —
list_threadshangs in scheduled Desktop runs; this incident also affects an interactive SSH controller and create/read/send operations. - #36404 — live task-tool handlers/routes can disappear while the underlying app-server remains healthy; this incident is not Voice-specific and manifests as indefinitely pending calls.
- #30626 — child creation from an SSH executor can place projectless children on the local host.
- #23418 — remotely created tasks can lose project association.
- #28080 — Desktop task tools can intermittently lose handlers.
- #35894 — dynamic tool request routing/response ownership may allow the wrong subscriber response to win.
This report is not claiming that all related issues share one internal root cause. It documents that their user-visible failure modes can compose into one unsafe end-to-end outcome.
Suggested engineering investigation
- Correlate each agent-facing task-tool request with the owning Desktop connection, destination host, handler, callback, and final response.
- Record whether a timed-out creation request was accepted or persisted before retry.
- Make project creation idempotent across client retries.
- Enforce target semantics in the tool host, not only in natural-language tool guidance.
- Reject
projectlessfor prompts or delegated contexts that require a saved repository unless the user explicitly approves the target change. - Carry parent host affinity into projectless child creation or require an explicit host.
- Validate the child destination host/project before beginning its first turn.
- Return a structured timeout or overload error instead of leaving the call pending indefinitely.
- Add an integration test covering Windows Desktop -> saved Linux SSH project -> delegated project worktree task, including handler loss and retry.
Privacy review
This report intentionally excludes:
- repository and organization names;
- project IDs and saved project labels;
- branch and commit identifiers;
- parent and child task, turn, request, connection, and host identifiers;
- Windows username and Linux absolute paths;
- prompt and source-code contents;
- business data, credentials, tokens, and authentication files;
- raw rollout, SQLite, and Desktop log files.
Narrow sanitized excerpts and identifiers can be provided privately through an OpenAI-controlled support or in-app feedback channel if maintainers need them.
5 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Additional macOS local-controller reproduction
I can reproduce the same indefinitely pending Desktop thread-tool boundary without a projectless fallback or an SSH repository operation.
Environment:
26.727.51351(build6119)codex-cli 0.146.0-alpha.9.227.0build26A5388g, Apple SiliconObserved across a long-lived Studio Director task:
list_threadswas advertised and invoked from both user-driven turns and active-goal continuations.240,50,20,10,5, and finally pinned-only0produced no metadata, partial result, typed error, permission prompt, or transport payload before bounded termination.limit: 0control still remained pending for approximately 52 seconds across the initial call and one same-call continuation. This makes result volume and ordinary pagination unlikely explanations.read_threadcalls for two known targets and an immediatewait_threads(timeoutMs: 0)snapshot also failed to return in earlier bounded controls.Same-day aggregate app-log review found zero
No handler registeredentries, but did contain one sanitized queue event forthread/listwithreason=queue-expired,queueWaitMs=30001, andinFlightRequestCount=3, plus onethread_list_unavailableoccurrence. I am not claiming those events are the root cause or that they correlate to every call; they are offered as a narrow diagnostic lead. Raw logs and session transcripts are intentionally not shared publicly.Operational impact: durable peer tasks and their local artifacts remain healthy, but the controller cannot safely verify current task/host identity or deliver a deduplicated handoff. We now fail closed through a local outbox with zero attempts rather than treating the user or target owner as blocked.
Expected behavior remains: return task metadata, a typed per-target failure, or a bounded timeout that identifies queue/handler/host/indexing state. An advertised thread tool should not remain pending without a trustworthy side-effect state.
This looks related to #35030, but the useful delta here is that the failure is also observed in the local controller outside a naturally scheduled automation, and
limit: 0does not recover it.Confirming the same failure on 2026-08-09 with Codex App
codex-cli 0.147.0-alpha.6.5(/Applications/Codex.app/Contents/Resources/codex --version)controlling a saved Linux Remote SSH project. The remote Codex CLI/app-server was0.147.0.Additional observations from this reproduction:
projectless, because that would lose the saved project and remote-host guarantees described in this issue.This strengthens the evidence that the stale boundary can be in the Desktop task-management bridge or response-delivery path while the managed remote app-server itself remains alive. A bounded timeout plus an explicit “side effect accepted/not accepted” result would make retries safe.
@Lady-Lin : I suggest you change the title to
Codex Desktop Remote SSH: thread-management RPCs hang indefinitely while app-server stays healthyso other people encountering this issue can more easily find it and add a 👍I can reproduce a closely related failure in Codex Desktop on Windows.
During a voice session, task listing and task monitoring repeatedly hung without returning a result, even though the current conversation remained usable. I fully exited and reopened Codex, restarted Windows, and signed out and back in; the task-management timeout persisted after each step. The public status page showed Codex operational.
I submitted a performance trace while reproducing one clean task-list timeout.
Feedback ID: 01a01096-1458-7a33-b6ed-d8badcb0c27b
EDIT: I was able to access everything when I retried in a non-voice thread, so my error is specific to voice coordination.