Skip to content

Codex Desktop intermittently exposes thread tools without registered handlers #36673

Open

Description

@futurenowlabs

Summary

Codex Desktop intermittently exposes the codex_app thread-management tools to the model, including their complete schemas, but invocation fails with:

No handler registered for tool: <tool_name>

The failure has affected at least:

  • list_threads
  • read_thread
  • send_message_to_thread

The same tool can fail and later succeed in the same resumed Desktop thread. This appears to be a Desktop/app-server dynamic-tool handler registration or routing problem rather than the target thread being absent.

Environment

  • Codex Desktop version: 26.727.51351
  • Bundle build: 6119
  • Bundle identifier: com.openai.codex
  • macOS: 26.5 (build 25F71)
  • Architecture: Apple Silicon / arm64
  • Observed: 2026-08-02 through 2026-08-03

Reproduction

  1. Open or resume a long-lived Codex Desktop thread that coordinates another existing remote task.
  2. Inspect/search the available tool surface.
  3. Confirm codex_app.list_threads, codex_app.read_thread, and codex_app.send_message_to_thread are present with complete schemas.
  4. Invoke one of those tools.
  5. Intermittently observe:
    No handler registered for tool: list_threads
    
    or the equivalent error for read_thread / send_message_to_thread.
  6. Retry later in the same local thread. A read-only tool such as list_threads may succeed and return the existing remote task, then fail again on a subsequent invocation.

The issue was observed around resumed-thread use, heartbeat wakeups, and context transitions, but a single exact trigger has not yet been isolated.

Expected behavior

  • Any thread-management tool exposed to the model must have a registered callable handler for that turn.
  • If the target thread or remote host is unavailable, return a specific target/host/session error rather than a missing-handler error.
  • Mutating calls such as send_message_to_thread must have an unambiguous completion result so callers can safely decide whether retrying is allowed.

Actual behavior

  • Tool schema discovery succeeds while invocation reports that no handler is registered.
  • Registration appears intermittent within one local thread.
  • The target remote task can still be listed as existing and active between failures.
  • Other connector tools continue to work, so the failure appears isolated to the Desktop thread-management bridge.

Safety / exactly-once concern

send_message_to_thread can return the missing-handler error while the target task later appears active or has a newer update timestamp. It is therefore unclear whether the write definitely did not happen.

This creates a duplicate-action risk: blindly retrying a deployment, rollback, or other operational instruction could submit it twice. The API should return a definitive result or an idempotency/operation identifier.

Related issues

This report differs because the affected tools are present in the advertised tool surface, but their handlers intermittently cannot be invoked.

Additional information

No private thread IDs, repository names, host identifiers, prompts, message bodies, credentials, or runtime contents are included in this report.

Activity

  1. added
    bugSomething isn't working
    appIssues related to the Codex desktop app
    app-serverIssues involving app server protocol or interfaces
    tool-callsIssues related to tool calling
    sessionIssues involving session (thread) management, resuming, forking, naming, archiving
    on Aug 3, 2026
  2. ESKehler commented on Aug 4, 2026

    @ESKehler

    Windows same-process reproduction with concurrent saved tasks

    I captured a new Windows reproduction that narrows the lifecycle boundary considerably.

    Environment

    • Windows 10 Home x64, build 19045
    • Codex Desktop package: 26.727.6591.0
    • Desktop app-server requests identify the client as Codex Desktop 26.727.51351
    • Bundled runtime model-cache version: 0.146.0
    • 15.9 GiB RAM; Intel Core i7-7700HQ
    • The app and codex.exe process started at 2026-08-04 16:45:37 UTC and remained running throughout the principal reproduction.

    Principal timeline (UTC)

    Three saved tasks overlapped:

    • 22:34:19.779 — task C started and remained active.
    • 22:37:48.426 — task A started.
    • 22:38:05.837 — task A completed tool discovery; the returned codex_app namespace explicitly contained list_threads with its full schema.
    • 22:38:09.615 — task A invoked list_threads.
    • 22:38:10.052 — after 437 ms: No handler registered for tool: list_threads.
    • 22:39:02.312 — task B started.
    • 22:39:10.799 — task B completed discovery exposing read_thread.
    • 22:39:13.752 — task B invoked read_thread.
    • 22:39:14.167 — after 415 ms: No handler registered for tool: read_thread.
    • 22:39:36.065 — task B invoked list_threads.
    • 22:39:36.572 — the same missing-handler error returned.
    • 22:42:13.155 — task A completed normally; the model/app-server was not generally dead.
    • 22:59:20.980 — task B repeated tool discovery successfully.
    • 22:59:23.982 — task B immediately retried list_threads.
    • 22:59:24.417 — missing-handler failure returned again.

    This shows that discovery and invocation disagreed within 3–4 seconds, the condition crossed task boundaries, it persisted for more than 21 minutes, and rediscovery did not repair registration. Unrelated shell and GitHub connector calls continued working.

    Same-process success/loss/recovery evidence

    The same saved coordinator task recorded this sequence earlier on August 4:

    UTC Tool Result
    14:52:16.545 read_thread success
    14:52:22.074 read_thread missing handler, only 5.5 seconds later
    15:18:30.267 list_threads success
    15:22:52.457 read_thread missing handler
    15:26:29.251 read_thread success without restarting
    15:44:02.244 send_message_to_thread missing handler
    15:56:06.944 send_message_to_thread missing handler
    16:49:22.777 / 16:49:48.629 read_thread success after restart
    17:07:14.904 list_threads success in the same process that later failed
    22:39:14.167 read_thread missing handler
    22:39:36.572 list_threads missing handler

    This demonstrates both loss and recovery without a restart, plus only temporary recovery after restart. A second saved task has repeated list_threads success/failure alternation across July 27, July 29, August 1, August 3, and August 4.

    Context-size control

    At the principal failure:

    • task A was at approximately 70% of a 258,400-token context window;
    • task B was at approximately 35%;
    • concurrent task C was at approximately 42%.

    Long-lived tasks and concurrent hydration may increase exposure, but a near-full context is not required: task B failed at only 35%.

    Evidence source and likely boundary

    Exact calls/results came from durable per-task rollout records. The matching rows in the live SQLite log were visible immediately after the incident but were pruned during the investigation, so complete raw logs are not durable enough for delayed reporting.

    The strongest inference is divergence between the advertised deferred-tool catalog and the live Desktop handler registry, potentially exposed by concurrent task activation: discovery returns one catalog generation, invocation finds no corresponding handler, another task sees the same missing registry shortly afterward, and rediscovery returns the schema again without repairing it.

    Useful fixes/diagnostics would be:

    • make schema publication and handler registration atomic per turn/client generation;
    • log a handler-generation ID at discovery, dispatch, renderer selection, and response;
    • revalidate/rebind handlers at task start/resume, context restoration, Remote Control connection changes, and concurrent-turn activation;
    • omit tools whose handler is absent, or return a structured recoverable availability error;
    • give mutating calls a stable operation ID plus delivered, not_delivered, or unknown semantics;
    • add a stress test with three concurrent saved tasks repeatedly discovering/invoking list_threads and read_thread while switching the active task.

    No task IDs, local paths, usernames, prompts, project data, credentials, or complete logs are included.

  3. quiezent commented on Aug 6, 2026

    @quiezent

    Additional Windows heartbeat reproduction (send_message_to_thread)

    I reproduced the same advertised-tool / missing-handler mismatch in a long-lived scheduled-task coordinator.

    Environment

    • Codex Desktop package: 26.727.6591.0 (OpenAI.Codex_26.727.6591.0_x64__2p2nqsd0c76g0)
    • Windows 11 Pro x64, version 10.0.26200, build 26200
    • Observed at approximately 2026-08-05 16:05 UTC (2026-08-06 00:05 Asia/Kuala_Lumpur)
    • The affected task is a long-lived heartbeat/scheduler coordinator that sends neutral status notices to existing saved tasks.

    Reproduction

    1. A scheduled checkpoint woke the existing coordinator task.

    2. Top-level tool discovery returned codex_app__send_message_to_thread with its complete callable schema, including hostId, threadId, and prompt.

    3. The coordinator immediately invoked it with hostId: "local" and a known existing destination thread.

    4. The call returned in about 0.5 seconds with:

      No handler registered for tool: send_message_to_thread
      
    5. Web/time and GitHub connector calls continued to work, so the task and tool system were not generally unavailable.

    The intended checkpoint had three existing recipient tasks and used sequential delivery. I stopped after the first handler failure to avoid duplicate or ambiguous delivery. Result: 0/3 deliveries confirmed.

    This adds a scheduler/heartbeat-specific Windows reproduction where no list_threads or read_thread call was required: discovery advertised send_message_to_thread, but its Desktop-side handler was absent at dispatch. The failure prevents reliable scheduled cross-thread notifications.

    For mutating sends, a definitive delivered, not_delivered, or unknown result (ideally with an operation/idempotency ID) would make safe retry behavior possible. No task IDs, message bodies, project data, local paths, or credentials are included here.

  4. ESKehler commented on Aug 26, 2026

    @ESKehler

    Current control: core thread path succeeds, but one advertised list_threads field is rejected

    A fresh end-to-end control on Windows produced a useful mixed result. Computer Use was disabled and absent from the active skill catalog throughout.

    Results

    1. Unfiltered list_threads succeeded and discovered the target task by title.
    2. read_thread succeeded.
    3. In that same source task, the live list_threads tool description advertised an optional query field, but:
      list_threads({query: ...})
      -> Unrecognized key: query
      
    4. A first inline send_message_to_thread wrapper failed before dispatch with:
      SyntaxError: Unexpected string
      
    5. Repeating the same send using a separately constructed arguments object succeeded.
    6. wait_threads returned the target task's exact response in approximately 4.4 seconds.
    7. The visibly selected Codex task never changed during discovery, read, send, or wait.

    Interpretation

    • Thread discovery/read/send/wait are independent of Computer Use and can work end-to-end while it is disabled.
    • The query result is a direct schema/implementation mismatch: one task receives a published schema that the invocation validator rejects.
    • The one wrapper SyntaxError is not established as a thread-tool handler bug because it occurred before dispatch and the equivalent constructed-args call succeeded. It may be caller-side wrapper/string construction; it is included only to preserve the observed boundary.
    • Background thread coordination does not require the target task to become visibly selected.

    This complements the missing-handler cases in this issue: even when handlers are registered and the core route works, different tasks can receive incompatible argument schemas.

    Useful fixes/tests:

    • generate publication and validation from one canonical schema version;
    • include a schema/catalog generation ID in discovery and validation errors;
    • add a test that invokes every advertised optional field, including list_threads.query;
    • keep send results explicit enough to distinguish pre-dispatch failure from delivered/unknown.

    No thread IDs, task titles, message bodies, project paths, host identifiers, usernames, or private task content are included.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    appIssues related to the Codex desktop appapp-serverIssues involving app server protocol or interfacesbugSomething isn't workingsessionIssues involving session (thread) management, resuming, forking, naming, archivingtool-callsIssues related to tool calling

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions