[macOS Desktop plus Android Remote] list threads reaches app server but never completes; UI sidebar remains healthy.
What version of the Codex App are you using (From “About Codex” dialog)?
26.810.41047
What subscription do you have?
Pro x 20
What platform is your computer?
Darwin 24.6.0 arm64 arm
What issue are you seeing?
The Desktop UI continues to show projects, pinned chats, and recent chats, but agent-facing codex_app thread-management calls are unreliable on both Desktop and Android Remote.
An agent list_threads call can remain pending indefinitely with no structured error, preventing a fresh task from discovering existing conversations that are visible in the UI.
Remote project creation also failed with:
create_thread received invalid arguments
What steps can reproduce the bug?
- Pair ChatGPT on Android with a local macOS Codex Desktop host.
- Confirm that projects and existing chats remain visible in the Desktop UI.
- From an agent task, call
codex_app.list_threads. - Observe that the call can remain pending indefinitely without a result or structured error.
- Restart Desktop and retry. The UI sidebar can still list chats, while a later agent-facing list call again fails to settle.
Read-only log evidence from the failing session:
- Immediately after restart, UI-originated
thread/listcompleted in roughly 1–11 ms. - Later, four
thread/listrequests reached the local app-server. - No matching completion/response record was logged for those request IDs.
- After pending calls were cancelled, the app-server logged
CancelledErrorfollowed bycould not find callback. - Unrelated account, configuration, filesystem, and thread-read requests continued to complete promptly.
What is the expected behavior?
Every codex_app thread-management call should return either a result or a structured, bounded timeout/error.
Agent-facing thread discovery should not fail while the Desktop UI can list the same chats. Remote project discovery must return identifiers accepted by project task creation for the same caller.
Additional information
The session index JSONL and global JSON parsed successfully, and the thread-state SQLite database passed its integrity check. No local state was modified.
No correlated Remote-disconnect, EPIPE, or thread_list_unavailable event appeared in the inspected log window.
Related issues: #32553, #36404, and #37668. This case is closest to that family but differs from #37668 because the local thread/list requests did reach the app-server before failing to settle.
Prompts, absolute paths, conversation IDs, and raw logs are intentionally omitted for privacy; redacted diagnostics can be provided through a private support channel.
5 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Additional current-build reproduction from macOS desktop scheduled automation:
26.810.52044(build6662)0.148.0-alpha.926.5.2arm64A standalone projectless cron automation called
list_threads({ limit: 10 })exactly once, sequentially, with no other thread-management calls in flight. The call did not return within 30 seconds. The samelist_threads({ limit: 10 })call from a foreground interactive task completed in 1.44 seconds, and later in 1.17 seconds. Restarting Desktop does not prevent the failure from recurring in later tasks.Local integrity controls all passed:
PRAGMA quick_check:okcodex doctor --json: state databases and provider/WebSocket reachability healthyAn additional correlated finding may explain why the task-service path becomes overloaded:
read_thread({ includeOutputs: false, maxOutputCharsPerItem: 1000, turnLimit: 1 })returned a 3,809,394-byte response for a completed thread because threeimageGeneration.resultblobs were included without truncation (approximately 1.40 MB, 1.32 MB, and 1.05 MB). The tool ignored bothincludeOutputs: falseandmaxOutputCharsPerItemfor those items.The active rollout inventory also contained three legacy histories of approximately 566 MB, 374 MB, and 178 MB. The built-in
migrate-rolloutsdry run marked all three eligible for paginated history. Migrating two completed histories and archiving those completed tasks restored foregroundlist_threads(limit: 10)latency to 1.17 seconds, but this does not explain or fix why the standalone scheduled call can remain pending while the foreground call succeeds.This provides two likely interacting defects:
read_threadcan return multi-megabyte image payloads despite explicit output suppression/truncation, increasing queue and memory pressure.No private paths, prompts, task titles, identifiers, or raw logs are included here. I can provide narrow correlation details privately if needed.
Additional sanitized current-build reproduction narrows the hang to the return leg after the App Server has already answered.
Environment:
26.820.7780.0, ARM640.149.0-alpha.4.1list_threads({ limit: 10 })Observed:
dynamic_app_tool_renderer_execution_startedforlist_threads.thread/listrequests reachedAppServerConnection.errorCode=null,hadPending=true, andtargetDestroyed=false.Sending server response ... tool=list_threadsevent.list_threadsfunction call with no function-call output and remains unchanged for more than 43 minutes.list_threadsduring the same incident; it also remained pending until manually interrupted after 495.8 seconds.read_threadandwait_threadsoperations remained responsive, and unrelated App Server operations continued completing.Earlier
list_threadscalls in the same Desktop process normally completed in roughly 2-3 seconds. The first unreplied dynamic call appears to poison subsequent agent-facing list calls globally.This is one boundary later than the original reproduction: the request not only reaches the App Server, but successful
thread/listresponses are already routed. The unresolved promise is between the routed App Server response and the dynamic app-tool reply to the model.Expected: every dynamic task-tool request must settle with a result or bounded structured error. A successfully routed App Server response must not leave the model turn blocked indefinitely.
No task IDs, turn IDs, call IDs, paths, project names, prompts, account data, hostnames, addresses, or credentials are included.
Cancellation control from the same incident:
list_threadsbelonged to a turn that later persisted aturn_abortedevent;list_threadscall also remained unresolved;Therefore outer turn cancellation does not reliably cancel or reject the pending dynamic app-tool request. The leaked request survives
turn_abortedand appears to poison subsequentlist_threadscalls in the renderer bridge.Required invariant: aborting a turn must cancel every outstanding app-tool request, reject the model-visible tool promise, remove the call from bridge bookkeeping, and permit the next task-tool call to proceed. A stale request must not survive into later turns.
No task, turn, call, project, path, host, or account identifiers are included.
Recovery outcome from the same current-build incident:
turn_abortedfor the blocked outer turn in the durable rollout.list_threadscall had not settled naturally. Its model-visible output appeared only during cancellation, roughly 57 minutes after the original call.wait_threads, exact-IDread_thread, and dynamic command calls returned, and the new tool stream became visible in the UI.list_threadswas intentionally not retried, so this does not claim that the poisoned list route recovered.This confirms two separate recovery boundaries: Stop can terminate the outer turn, but the leaked dynamic request remains unresolved until cancellation; restoring normal renderer tool delivery still requires a renderer reload. Cancellation should settle the tool promise immediately and remove its bridge state without requiring a reload.
No task, turn, call, project, path, host, account, prompt, or credential identifiers are included.