Scheduled Codex Desktop runs hang on `list_threads` while interactive calls succeed

Open 💬 8 comments Opened Jul 23, 2026 by jm-fhc
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

Environment

  • Codex Desktop 26.715.72359 (build 5718)
  • codex-cli 0.145.0-alpha.30
  • macOS on Apple Silicon
  • Two connected macOS hosts using Codex Desktop Remote Control

Hostnames and all task identifiers are omitted for privacy.

Issue

Official Codex Desktop thread-management tools work interactively, including across connected hosts, but list_threads consistently fails to return from naturally scheduled automation runs.

Interactive tests succeeded in both directions:

  • list_threads returned local and remote tasks.
  • read_thread returned recent turns from both hosts.
  • set_thread_title renamed a task on the other host, and readback verified the change.

The same list_threads operation did not complete during scheduled runs, even though the tool was exposed with a valid schema.

Reproduction

  1. Connect two macOS Codex Desktop hosts through Remote Control and keep both online.
  2. In a fresh interactive task, verify that list_threads, read_thread, and set_thread_title are exposed.
  3. Interactively list tasks, read a task from each host, rename one on the other host, and verify the change. These operations succeed.
  4. Create a standalone scheduled automation whose first operation is a read-only list_threads call.
  5. Allow the automation to run naturally.
  6. Observe that list_threads remains pending or fails to return.
  7. Repeat with result limits of 50, 20, 10, and 5. All attempts fail before any task can be inspected or renamed.
  8. Run the equivalent scheduled automation against the connected remote host. Three natural scheduled runs fail in the same way.
  9. As a bounded control, make one scheduled send_message_to_thread call to a fixed idle control task. That call also fails to complete, while the corresponding interactive workflow works.

Expected behavior

A naturally scheduled task given the official list_threads tool should be able to call it as an interactive task can.

If thread operations are intentionally unavailable in scheduled runs, the tools should not be exposed there, or they should immediately return a structured and actionable error. They should not remain pending indefinitely.

Actual behavior

  • Interactive local and cross-host thread operations succeed.
  • Naturally scheduled list_threads calls consistently fail on both tested hosts.
  • Reducing the requested result count does not help.
  • The scheduler starts each run and delivers the prompt; failure begins at the Codex Desktop app-tool call.

The automations were paused after the bounded reproduction attempts.

Related issues

  • #33503 — mentions a list_threads hang in a full-suite scheduled run.
  • #31584 — a macOS scheduled automation stalled on codex_app.list_projects.
  • #28080 — Desktop thread tools intermittently lose their handlers.
  • #21995 — scheduled app-connector calls fail while later manual execution succeeds.

View original on GitHub ↗

8 Comments

github-actions[bot] contributor · 1 month ago

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

  • #34295

Powered by Codex Action

jm-fhc · 1 month ago

Post-update reproduction

Retested after updating both connected macOS hosts:

  • Codex Desktop 26.721.30844 (build 5813)
  • codex-cli 0.146.0-alpha.3

Interactive control still passes: list_threads(limit: 15) returned immediately across both connected hosts, with no unavailable hosts.

One bounded naturally scheduled canary was then run on the updated build. It launched normally, received its prompt, and called list_threads(limit: 10) exactly once. That call never returned. The scheduled run ended after approximately 194 seconds.

Because the first call did not return:

  • read_thread was not issued
  • set_thread_title was not issued
  • readback was not issued
  • no retry was made
  • no title was changed

The automation’s original prompt and recurrence were restored exactly, and it was left PAUSED.

A second post-update controller on the other host still did not expose automation_update, so no additional scheduled canary was armed there and no persistence files were edited manually.

Separate compatibility observation: the controller-side tool schema advertised a query argument for list_threads, but the updated Desktop handler rejected it with Unrecognized key: "query". Calls using only limit continued to work interactively.

Result: the scheduled-run list_threads failure remains reproducible on 26.721.30844 / 0.146.0-alpha.3.

Yevanchen · 1 month ago

Additional observation from a scheduled automation run on 2026-07-29 (macOS):

  • The automation made exactly one list_threads(limit=25) call.
  • It waited about 53 seconds, then the tool wrapper completed with no thread-list payload (undefined).
  • The run therefore made no pin/archive changes. The automation deliberately does not retry, to avoid duplicate lifecycle mutations when list state is unknown.

This is a bounded failure rather than an indefinite pending call, but it has the same operational impact: a scheduled task cannot safely inspect or manage threads. A structured timeout/error result would let automations report the failure reliably without guessing state.

BsnizND · 19 days ago

Newer-build reproduction

Reproduced again on macOS Apple Silicon with:

  • Codex Desktop 26.803.41515 (build 6321)
  • bundled codex-cli 0.147.0-alpha.6.5

A natural scheduler-origin task launched normally and successfully completed a preceding fixed read-only helper call. It then made exactly one standalone codex_app list_threads({limit: 50}) call. That call remained pending for about 4m46s until the task terminated it.

No retry, alternate inventory path, thread read, task creation/continuation, or external action occurred. The affected automation was immediately paused.

An interactive list_threads call approximately 15 seconds earlier returned successfully. Its underlying local app-server thread/list response completed in about 3 ms and included the active automation task.

Additional implementation evidence from the packaged Desktop build:

  • the local-host branch already sends useStateDbOnly: true, so JSONL scan/repair is not the cause in this reproduction;
  • the projected codex_app list_threads schema exposes only limit;
  • the Desktop wrapper aggregates pinned state, connected Codex hosts, ChatGPT history, and pinned hydration, without an aggregate timeout.

Expected: a naturally scheduled task can use the exposed official tool, or receives a structured actionable error.

Actual: the tool remains pending, preventing collision-safe unattended automation.

Private task identifiers and local paths are omitted here and can be supplied through a private support channel if useful.

quiezent · 16 days ago

Windows reproduction: automation_update and send_message_to_thread hang in the same natural scheduled run

I reproduced the same scheduled-run tool-routing failure family on Windows, with an additional high-impact failure mode: a heartbeat cannot reliably advance its own next checkpoint because both the schedule update and all recovery notifications can hang together.

Environment
  • Codex Desktop 26.803.10989.0
  • Windows 10.0.26200, x64
  • Naturally fired heartbeat automation
  • Private task IDs, automation IDs, project paths, account details, and workflow content are intentionally omitted
Observed sequence

A time-sensitive heartbeat fired normally and received its prompt. Its contract required it to update the same heartbeat to the next checkpoint before dispatching several independent messages.

  1. The run issued exactly one full-field codex_app automation_update call, changing only the recurrence for the next checkpoint.
  2. The call produced no response for about 47 seconds and was terminated by the task's bounded timeout.
  3. Because a side-effect may have occurred, the task correctly did not retry the update.
  4. A bounded automation_update(mode: "view") verification call also failed to return within 20 seconds.
  5. The run then issued one send_message_to_thread attempt to each of five fixed existing threads. All five calls failed to return within 20 seconds.
  6. A final automation_update(mode: "view") call also timed out.

All message deliveries and the schedule mutation therefore had to be classified as ambiguous. No automatic retry was made.

This occurred after an earlier natural scheduled run showed the same update symptom. A separate controller later verified that the earlier timed-out update had not changed the persisted recurrence and had to repair it with one full-field update. Without that external repair, the heartbeat would have remained on its old weekly time and the next intra-day checkpoint would have been skipped; its next natural run would have been one week later.

A later run again reached the scheduled prompt successfully but then lost the app-tool response path for both automation_update and send_message_to_thread.

Expected behavior
  • Exposed app tools should complete in naturally scheduled runs as they do from a healthy controller, or return a structured, bounded, actionable error.
  • A side-effecting automation_update should return a definitive mutation result and an idempotency token/status that can be queried safely.
  • A readback should expose machine-readable automation ID, target, status, stored recurrence, and computed next-run time.
  • Failure of one message recipient should not affect schedule persistence or unrelated recipients.
  • A scheduler/tool failure should still leave a reliable route for reporting the incident.
Actual behavior and impact
  • The scheduler launches the run and delivers its prompt.
  • The first app-tool mutation can remain pending with unknown side-effect state.
  • Readback can hang as well, so the run cannot determine whether it is safe to retry.
  • Thread-message calls can fail simultaneously, preventing both normal dispatch and escalation.
  • A self-advancing heartbeat can silently remain on the previous weekly recurrence, deleting all later checkpoints from the effective schedule until another controller repairs it.

This creates one shared failure domain across scheduling, delivery, verification, and incident reporting. It is especially unsafe for time-sensitive unattended workflows because the correct no-duplicate behavior (do not retry an ambiguous mutation or send) also means there is no in-band recovery path.

Suggested engineering investigation
  • Trace scheduled-run dynamic-tool request ownership and response routing for automation_update, automation_update(view), and send_message_to_thread.
  • Add an aggregate timeout that returns a structured error instead of leaving calls pending.
  • Add request-level idempotency for schedule mutations and thread sends so callers can safely query or retry.
  • Return the persisted record plus computed next-run instant from update/view calls.
  • Test a natural heartbeat run that updates its next recurrence and then sends to multiple existing threads, including one failing recipient.
  • Ensure scheduler persistence and thread-message delivery do not share a single handler/route whose loss disables both.

No raw logs or private Codex state are attached. Narrow sanitized identifiers and timestamps can be supplied privately through an OpenAI-controlled support channel if maintainers need correlation data.

quiezent · 13 days ago

Follow-up Windows reproduction: intermittent failure after a healthy run in the same task

Reproduced again on 2026-08-14 in a naturally fired Windows Desktop heartbeat. This follow-up adds an important control: the immediately preceding checkpoint in the same automation task completed its full-field recurrence update, card readback, and three fixed-thread sends successfully. The next natural checkpoint then lost the response path for all of those app tools together.

Sanitized sequence:

  1. The heartbeat fired normally at approximately 14:02 ET and received its prompt.
  2. It issued exactly one full-field automation_update, changing only the recurrence to the next checkpoint. The wrapper received no result within its 20-second bound.
  3. It issued exactly one automation_update(mode: "view") readback. That also received no result within 20 seconds.
  4. Because the mutation outcome was ambiguous, it did not retry.
  5. It then issued one native send_message_to_thread attempt to each of three fixed existing threads. All three received no result within 20 seconds.
  6. The sends were classified as delivery-uncertain and were not retried.

The preceding natural checkpoint, roughly two hours earlier in the same task and session, returned promptly for the equivalent update/view/send sequence. This suggests the scheduled-run route can degrade intermittently without a task, prompt, target, or topology change, rather than being a permanently unsupported operation.

Operational impact remains the same: the task cannot determine whether its next recurrence persisted, cannot safely retry, and cannot know whether any recipient received the dispatch.

No private task IDs, automation IDs, account details, project paths, or workflow content are included.

Poolzoon · 12 days ago

I can confirm the same failure on Windows.

Environment
Codex Desktop 26.810.52044
Embedded codex-cli 0.148.0-alpha.9
Windows 11 Pro (OS build 26200.9168)
Scheduled automation running locally in Codex Desktop

An hourly local automation stalled on codex_app__list_threads({limit: 20}) in six consecutive naturally scheduled runs. A separate bounded diagnostic then made 12 scheduled single-call probes, cycling limits 1, 5, and 20; all timed out. The scheduler delivered each prompt, but execution stopped at the app-tool call.

Our temporary local-only workaround is:

  1. Enumerate currently held files under %USERPROFILE%\.codex\thread-writer-locks.
  2. Use CODEX_THREAD_ID to identify the current run.
  3. Call read_thread(hostId: "local", turnLimit: 1, includeOutputs: false) for each held task ID.
  4. Ignore internal helper locks that return No Codex thread found; count only other tasks whose status.type is active.
  5. Fail closed on any read error or ambiguous state.

That gate completed in about 3.3 seconds in our test. It relies on an undocumented implementation detail and only covers local Codex tasks, not remote/ChatGPT tasks, so it is a workaround rather than a general fix.

atlys-hein · 10 days ago

Fresh reproduction on 2026-08-18 with Codex CLI 0.147.0:

  • A Codex Desktop scheduled “Sidebar Cleanup” task resolved the official task-management tool and called codex_app__list_threads({ limit: 200 }).
  • The call remained pending through multiple 30-second waits, returned neither task data nor a structured error, and had to be terminated.
  • No sidebar tasks could be reviewed, renamed, or archived.
  • The automation had full local permissions, but the failure occurred at the Desktop task-management call rather than filesystem or repository access.

Expected: list_threads should return the Codex task catalog or a bounded, actionable error during scheduled runs.

Diagnostics were uploaded through /feedback. Uploaded thread ID: 01a014a5-4343-7f23-b239-bb052fb6ab91.