Codex Desktop Remote SSH: thread-management RPCs hang indefinitely while app-server stays healthy

Open 💬 5 comments Opened Aug 1, 2026 by Lady-Lin
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

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:

  1. official Desktop thread-management calls stop returning;
  2. no structured timeout or project-creation error is delivered;
  3. the agent changes the semantic target from project to projectless, despite an explicit tool contract forbidding that for repository work;
  4. project identity is lost by construction;
  5. projectless routing loses SSH host affinity and can place the repository task on the local Windows computer;
  6. 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: local and 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:

  • projectId was 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 add completed 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

  1. A project-scoped task creation request must return promptly with a ready identity, a pending-worktree identity, or a structured actionable error.
  2. Pending tool calls must have bounded timeouts and preserve whether a side effect may have occurred.
  3. A failed or timed-out project target must never be silently replaced with projectless.
  4. Repository work should fail closed or require explicit user confirmation before changing target semantics.
  5. Projectless creation from a remote executor should inherit the executor host, require an explicit destination host, or fail closed.
  6. Creation results should always expose the actual destination host, project association, and canonical task identity.
  7. A wrong-host or no-project destination should be detected before the child begins work.
  8. 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_threads hangs 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 projectless for 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.

View original on GitHub ↗

5 Comments

github-actions[bot] contributor · 27 days ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #36404

Powered by Codex Action

Coldain · 24 days ago

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:

  • Codex/ChatGPT Desktop 26.727.51351 (build 6119)
  • bundled codex-cli 0.146.0-alpha.9.2
  • macOS 27.0 build 26A5388g, Apple Silicon

Observed across a long-lived Studio Director task:

  • list_threads was advertised and invoked from both user-driven turns and active-goal continuations.
  • Calls at result limits 240, 50, 20, 10, 5, and finally pinned-only 0 produced no metadata, partial result, typed error, permission prompt, or transport payload before bounded termination.
  • The pinned-only limit: 0 control 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.
  • Exact read_thread calls for two known targets and an immediate wait_threads(timeoutMs: 0) snapshot also failed to return in earlier bounded controls.
  • No retry with changed target semantics, no projectless fallback, no task creation, and no message delivery was attempted while state was unknown.

Same-day aggregate app-log review found zero No handler registered entries, but did contain one sanitized queue event for thread/list with reason=queue-expired, queueWaitMs=30001, and inFlightRequestCount=3, plus one thread_list_unavailable occurrence. 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: 0 does not recover it.

saidelike · 19 days ago

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 was 0.147.0.

Additional observations from this reproduction:

  • The entire Desktop task-management RPC path stopped returning, including project discovery, task listing/reading, and project-scoped task creation.
  • Calls remained pending for roughly 90–300+ seconds without a structured timeout, error, pending-worktree ID, or task ID.
  • The remote app-server process remained alive and its Unix control socket remained listening.
  • Ordinary shell, Git, SQLite, and issue-tracker operations on the same remote host remained responsive.
  • Read-only inspection of the thread-state database, task queue, and Git worktree list confirmed that the canceled creation attempts produced no task, queued setup, or worktree.
  • The failure repeated across three consecutive controller turns.
  • I deliberately did not fall back to projectless, because that would lose the saved project and remote-host guarantees described in this issue.
  • Fully restarting Codex Desktop immediately recovered the bridge: project discovery returned in about 0.5 seconds, and project/worktree task creation returned in about 1.1 seconds with the correct Remote SSH host and a pending task identity. The resulting visible task and worktree then initialized normally.
  • No repository, branch, project, or remote app-server configuration was changed between the failure and recovery.

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.

saidelike · 19 days ago

@Lady-Lin : I suggest you change the title to Codex Desktop Remote SSH: thread-management RPCs hang indefinitely while app-server stays healthy so other people encountering this issue can more easily find it and add a 👍

KeroZelvin · 10 days ago

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.