Skip to content

Explicit steer is refused with "No running provider turn found" during run startup/completion gaps #23271

Description

@goleary

Summary

When a user sends a follow-up with the default Steer follow-up behavior while a run is active but has no running provider turn, the message is refused with No running provider turn found for active run <runId>. This happens when the run is starting, before the provider's first event, or in the gap as a turn finishes. The message isn't delivered.

#15600 / #15691 fixed this for deliveryIntent: "auto". The client sends an explicit deliveryIntent: "steer" whenever it sees a run as running and followUpBehavior is steer (the default), so the most common send path still hits the error.

Repro (observed on v0.1.1, Windows, Claude provider)

From the server trace and the provider event log for one thread:

  • 02:11:29.777Z: run ordinal:10 starts after a user message.
  • 02:11:32.676Z: user sends a follow-up. message.dispatch → Orchestrator.dispatchSteerIntoRun fails with OrchestrationV2DispatchCommandError: No running provider turn found for active run run:thread:…:ordinal:10.
  • 02:11:33.434Z: first native event from the Claude provider for that turn.

The follow-up stays in the composer and the user has to resend it.

Cause

In CommandPolicy resolveDeliveryIntent, explicit steer (and restart) return before the gap check that #15691 added:

if (deliveryIntent === "steer") return { type: "steer_active", targetRunId: activeRun.id };
if (deliveryIntent === "restart") return { type: "restart_active", targetRunId: activeRun.id };
if (activeRun.status === "preparing" || activeRun.status === "starting" ||
    !projection.providerTurns.some((t) => t.runAttemptId === activeRun.activeAttemptId && t.status === "running"))
  return { type: "queue_after_active" };

Expected

An explicit steer that arrives while the active attempt has no running provider turn shouldn't be rejected. It should be queued and delivered to the next or just-starting turn, as auto now is. From the user's side, steering a run that is just about to start and queueing for that run look the same.

Suggested fix

Apply the gap check to steer as well as auto: return queue_after_active when the run is preparing/starting or the active attempt has no running provider turn. Leave restart as it is. Add a steer row to the existing gap table in CommandPolicy.test.ts (absent, pending, completed, previous-attempt running).

Activity

  1. markshan00 commented on Oct 27, 2026

    @markshan00

    Adding a matching macOS observation, with sanitized timing evidence that may help with the startup-gap case. Thanks for tracking this down.

    Environment: macOS desktop, a locally localized build 0.1.2-zh.1 based on upstream v0.1.2, using the Claude provider with claude-opus-5-5. This was observed during normal use, not a synthetic stress test.

    Two occurrences were correlated using server spans, the provider protocol log, and read-only run/provider-turn projections. Times below are relative to each run's recorded startedAt; identifiers, message contents, paths, account configuration, and absolute timestamps are omitted.

    Observation Sample A Sample B
    Run recorded as running +0.000 s +0.000 s
    Follow-up rejected in Orchestrator.dispatchSteerIntoRun +9.887 s +26.049 s
    Provider turn's recorded start +12.911 s +30.106 s
    Startup checkpoint capture duration 12.890 s 30.041 s

    Both rejections reported:

    No running provider turn found for active run <redacted>.
    

    For sample A, the original prompt was offered to Claude at +12.912 s. The GitVcsDriver.checkpoints.captureCheckpoint span inside RunExecutionService.startRootRun took 12.890 s, including a Git subprocess taking 12.796 s. The original run subsequently completed; the rejected follow-up remained in the composer. Sample B's original run also subsequently completed.

    This supports a concrete way the startup gap becomes user-visible for seconds: the run is already recorded as running while baseline checkpoint capture is still pending, before the Claude provider turn exists. I have not investigated why those checkpoints were slow, so I am not attributing that to repository size or a particular Git operation.

    The upstream v0.1.2 source matches the issue's diagnosis: explicit steer returns before the no-running-provider-turn check, whereas auto queues. The web composer can send that explicit intent while the run reads as running.

    This is additional evidence for the reported failure only. I have not runtime-tested either proposed fix (#23559 or #25749) on this machine. No raw logs or screenshots are attached, to avoid exposing private workspace and conversation data.

  2. ebrardushullovcii commented on Oct 28, 2026

    @ebrardushullovcii

    Same bug here, T3 Code desktop on Windows 11 with the Claude provider (Opus 5.5).

    How I hit it: a scheduled automation posts a message into the thread, which starts a new run. If I send a message shortly after, it shows for under a second, then "No running provider turn found for active run run:thread:import:claudeAgent:...:ordinal:721." appears and the message goes back to my composer. Retrying fails the same way until the turn actually starts streaming.

    Two details that may help:

    • In my case the thread already showed "Working for 14s" and "Thinking" when the send was refused, so the gap can be longer than the 1-3 seconds in the trace above.
    • The thread was imported from Claude Code (run id starts with import:claudeAgent).
  3. bramtechs commented on Nov 1, 2026

    @bramtechs

    Another way to hit this: with an ACP provider (Antigravity), the turn restart caused by one steer leaves a gap of about a minute, and any steer sent during it is rejected.

    Environment: Windows 11 desktop, server at 9e09926d, Antigravity provider (claude-opus-4-6-thinking).

    What happened:

    Time (UTC) Event
    12:32:31 Run ordinal:4 starts with a user message
    12:33:24 Steer #1 is accepted
    ~12:33:30 to 12:34:13 Steer #2 is rejected with No running provider turn found for active run …:ordinal:4. Three retries failed the same way.
    12:34:13 The fourth retry is accepted once Antigravity has started the restarted turn

    Why this gap is longer: ACP adapters report supportsActiveSteering: false and supportsSteeringByInterruptRestart: true (packages/provider-acp/src/server/adapter.ts). Steer #1 therefore takes the interrupt-restart path in dispatchSteerIntoRun. That path moves run.activeAttemptId to the new attempt right away. The new attempt's provider turn only exists once the adapter has stopped the old ACP prompt and Antigravity has started the new one. The run reads as running throughout, so the composer keeps offering Steer. During that time the check at Orchestrator.ts (providerTurns.find(t => t.runAttemptId === targetRun.activeAttemptId && t.status === "running")) finds nothing.

    Both open fixes key on "the active attempt has no running provider turn", so #23559 and #25749 should cover this case as well. Nothing extra seems needed. I'm adding this because the gap here comes from a steer restarting the turn, not from run startup or completion, and it lasts much longer with ACP providers than the 1–3 s seen with Claude.

    I have not tested either PR against Antigravity.


    Written by Claude Code (Claude Opus 5.5) at the reporter's request.

  4. jamesdchen commented on Nov 2, 2026

    @jamesdchen

    Still reproduces on v0.1.6 (desktop, Windows), on a thread hosted on a linked/remote environment reached through the T3 Connect relay.

    • 2026-11-02T03:06:09Z and 03:06:14Z (client trace): two sends to the remote thread both failed in EnvironmentCommands.startThreadTurn → orchestration.dispatchCommand with
      OrchestrationV2DispatchCommandError: No running provider turn found for active run run:thread:<id>:ordinal:5.
    • This client's followUpBehavior is "queue", not the default steer. So the refusal isn't limited to the explicit-steer path described above, unless the client still sends deliveryIntent: "steer" in queue mode.
    • About 100 s later, at 03:07:52Z, the relay reported the remote environment disconnected. It hadn't come back by 03:15Z, though the host was reachable over Tailscale. So the remote run may also have been stuck in running with no provider turn, rather than in a short start/finish gap. I couldn't check the remote server's side.

    Expected: the follow-up is queued for the active run, or the run is reconciled, not dropped from the composer with this error.

    🤖 Generated with Claude Code

  5. ducktaperules commented on Nov 6, 2026

    @ducktaperules

    Current-nightly occurrence with 24 hours of supporting evidence

    Sending a message while a Claude run is starting can fail with No running provider turn found for active run .... T3 has already marked the run as running, but has not yet recorded a root provider turn for its active attempt. Repeated sends fail until that provider turn appears.

    Adding current-nightly evidence to this open report. The older automatic-delivery report #15600 was closed; our captured failures reach the steering dispatcher described here. We did not capture the outgoing deliveryIntent or client followUpBehavior, so those settings are not asserted. The roughly 30-second gap also resembles #28996, but checkpoint timing was not investigated in this collection.

    Environment

    • Windows x64 T3 desktop: 0.1.8-nightly.20261106.4262.
    • Remote Ubuntu/Linux x64 T3 server: 0.1.8-nightly.20261106.4262.
    • Provider instance: claudeAgent; model: claude-opus-5-5.
    • Both versions were checked through T3's environment API during this investigation. Today's desktop trace and Ubuntu server stack also identify this build. Yesterday's server version has not been independently verified.

    Observed behavior

    The send fails instead of being queued until the provider is ready. Failed commands have persisted status = rejected receipts and no orchestration events under their command IDs. The existing runs subsequently complete successfully.

    Today's exact error:

    No running provider turn found for active run run:thread:mcp%3Alaunch%3A0772fba6206ce86e6781c85f4be18d7c9771d893872efc2efa23023407fcf753:ordinal:14.
    

    The server stack places this error in Orchestrator.dispatchSteerIntoRun, through Orchestrator.dispatchMessage, orchestrationV2.dispatch.once, orchestrationV2.dispatch.withReceipt, and ThreadMessageIntake.dispatchCommand. The Windows client records it as OrchestrationV2DispatchCommandError in EnvironmentCommands.startThreadTurn.

    Evidence from the last 24 hours

    Window: 2026-11-05 12:24:18 UTC to 2026-11-06 12:24:18 UTC, fixed at the start of the investigation.

    There are 68 distinct rejected message.dispatch command IDs across six runs in two threads. This is a count of rejected commands, not a count of independent root-cause incidents or duplicate trace spans.

    • 12 commands today: exact error verified in both Ubuntu server and Windows client traces and correlated to the rejected receipts.
    • 56 commands yesterday: generic rejected receipts plus the same reconstructed state: the active run is running, but there is no root provider turn for its active attempt. These are corroborating instances; their exact error text is no longer available.

    All times below are UTC. Thread labels omit conversation titles and repository names.

    Date Thread / run Rejected sends, first-last Distinct commands Run marked running First provider-turn running event Gap
    2026-11-05 A / 45 14:34:46.048-14:34:46.048 1 14:34:16.692 14:34:46.788 30.096 s
    2026-11-05 A / 50 14:53:02.807-14:53:27.183 30 14:52:57.346 14:53:27.420 30.074 s
    2026-11-05 A / 85 15:46:48.635-15:46:51.254 3 15:46:21.856 15:46:51.932 30.076 s
    2026-11-05 A / 94 19:05:57.698-19:06:09.345 10 19:05:39.912 19:06:10.006 30.094 s
    2026-11-05 A / 100 19:23:14.897-19:23:23.736 12 19:22:54.415 19:23:24.491 30.076 s
    2026-11-06 B / 14 11:48:17.896-11:48:32.975 12 11:48:07.089 11:48:37.163 30.074 s

    All six runs have an approximately 30-second startup gap. All recorded rejections fall within that gap. This suggests a useful reproduction window, but the reason for the delay has not been established.

    Detailed current occurrence

    For thread B, run 14 on 6 November:

    1. 11:48:07.089: run and active attempt marked running.
    2. 11:48:17.896-11:48:32.975: 12 different message commands rejected with the exact error. All 12 have zero resulting orchestration events.
    3. 11:48:37.163: first root provider-turn.updated event with status = running; its startedAt is 11:48:37.155.
    4. 11:49:03.714: the original run completes.

    Example rejected command: 34a6b465-bf55-4a42-9fc8-2fcf0428d753. Representative trace records are included below. The other eleven rejects have different command IDs, so these failures are not simply replays of one rejected command ID.

    Expected behavior

    A normal send during provider startup should remain queued or otherwise be accepted for delivery when the provider is ready. A temporary absence of a provider turn should not make the message fail.

    Reproduction guidance

    Based on the captured failures, start a Claude turn and try sending another message while T3 shows the run as running but before its first root provider turn appears. The observed window was about 30 seconds in all six affected runs. This is a proposed reproduction based on captured state, not a newly executed controlled test.

    Collection and limits

    The investigation used read-only SQLite connections (mode=ro, query_only=ON) and existing trace files. It did not send messages, restart T3, change settings, or modify application state.

    Rejected commands came from orchestration_command_receipts. The generic receipt error alone does not establish the exact cause. Run and provider-turn state were reconstructed by replaying the relevant application-version-2 events from orchestration_events in sequence order through each receipt's result_sequence. Matching provider turns were restricted to the run's active attempt and root node. The reconstructed lifecycle event was checked to precede the rejection timestamp, and the first matching provider-turn event was checked to follow it.

    The 56 older rejected commands are in five bursts on one thread. Today's 12 are on a second thread. All six runs used Claude Opus 5.5 and later completed. Exact errors were retained only for today's case: the collected Ubuntu trace files have no spans older than 08:39 UTC on 6 November. Older rejections therefore must not be described as 56 independently confirmed occurrences of the exact error text.

    The evidence below excludes message text, conversation titles, repository names, credentials, and raw stack file paths. It retains command IDs, opaque run IDs, source filenames and line numbers, timestamps, and selected state fields. Source logs rotate; filenames and line numbers refer to the collection snapshot.

    The full per-command export is retained locally and can be provided if needed.

    Representative sanitized server and client trace records

    These describe the first of the 12 confirmed rejected commands. Nested spans are not counted as separate sends.

    {
      "server": {
        "file": "server.trace.ndjson.2",
        "line": 1654,
        "timestamp": "2026-11-06T11:48:17.893Z",
        "span": "Orchestrator.dispatchSteerIntoRun",
        "trace_id": "f5878903c02419efdc8737db56a72c8d",
        "command_id": "34a6b465-bf55-4a42-9fc8-2fcf0428d753",
        "run_id": "run:thread:mcp%3Alaunch%3A0772fba6206ce86e6781c85f4be18d7c9771d893872efc2efa23023407fcf753:ordinal:14",
        "error": "No running provider turn found for active run run:thread:mcp%3Alaunch%3A0772fba6206ce86e6781c85f4be18d7c9771d893872efc2efa23023407fcf753:ordinal:14.",
        "version": null
      },
      "client": {
        "file": "server.trace.ndjson.5",
        "line": 9062,
        "timestamp": "2026-11-06T11:48:18.361Z",
        "span": "EnvironmentCommands.startThreadTurn",
        "trace_id": "874c1a99fc7389403228f81155ade099",
        "command_id": null,
        "run_id": "run:thread:mcp%3Alaunch%3A0772fba6206ce86e6781c85f4be18d7c9771d893872efc2efa23023407fcf753:ordinal:14",
        "error": "No running provider turn found for active run run:thread:mcp%3Alaunch%3A0772fba6206ce86e6781c85f4be18d7c9771d893872efc2efa23023407fcf753:ordinal:14.",
        "version": "0.1.8-nightly.20261106.4262"
      }
    }

    Prepared with Codex (gpt-6.1-sol) at the reporter's request.

  6. jackroberts236 commented on Nov 6, 2026

    @jackroberts236

    Additional confirmed occurrence on macOS desktop, local server, 0.1.8-nightly.20261106.4262, using claudeAgent / claude-opus-5-5. This includes a completion → queued subagent-result wake-up → provider-startup handoff, with “always steer” enabled according to the reporter.

    The reporter saw a follow-up remain queued as the parent finished, then a citation-containing send was refused with:

    No running provider turn found for active run <redacted>.
    

    A citation-containing message was subsequently accepted. The captured failure occurs in Orchestrator.dispatchSteerIntoRun, rather than citation lookup.

    Correlated evidence (6 November 2026, UTC)

    Existing server/client traces, effect-outbox records and read-only lifecycle events show:

    1. 14:14:55.839: the parent provider turn completed; the run entered waiting. Its post-turn checkpoint capture took about 30.1 seconds and timed out.
    2. 14:15:20.575: the user's follow-up was accepted as a queued run while that finalization was pending. A subagent-completion delivery was already ahead of it in the queue. The logs do not establish that the child and parent actually finished simultaneously; the queued child-result delivery is the relevant overlap.
    3. 14:15:26.439: the subagent-result wake-up run was recorded as running, before its provider turn existed. Baseline checkpoint capture then took 30.042 seconds and failed; the server continued without a baseline.
    4. 14:15:50.611, 14:15:55.471 and 14:15:56.065: three distinct message.dispatch commands were refused with the error above, targeting that wake-up run.
    5. 14:15:56.496: the provider turn finally started. 14:15:56.640: the citation-containing message was accepted into that same run.

    A later Claude run repeated the startup gap: run marked running at 14:20:20.581, steer refused at 14:20:38.995, provider turn started at 14:20:45.607. This time baseline capture took about 24.99 seconds and failed with VcsProcessExitError / Git exit 128, rather than a timeout.

    A separate Codex thread on the same install also showed repeated refusals between its run being marked running at 14:20:49.054 and its first provider turn starting at 14:21:36.206. This supports a shared orchestration gap rather than a Claude- or citation-only failure.

    Fix scope

    The latest published nightly checked during triage, 0.1.8-nightly.20261106.4275 (6577c6b6185167c0e502fa01f9e8e8f2dee6ff25), still resolves explicit steer before checking whether a running provider turn exists. See the release's CommandPolicy. This is source verification, not a claim that the incident was reproduced on that newer build.

    Identifiers, conversation text and filesystem paths are omitted. Evidence collection used existing logs and SQLite connections opened with mode=ro; no live database writes were made.

    Prepared with Codex (gpt-6.1-sol) in T3 Code, at the reporter's request.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions