Skip to content

Steer is broken three ways on busy sessions: silent queue downgrade, abort-and-strand, restored-queue stall (v1.22.1/1.22.2) #3370

Closed

Description

@JustinKeltner

OpenChamber version

1.22.1 and 1.22.2 (reproduced on both; two independent machines, different settings)

Defect 1 — explicit Steer silently downgraded to a queue delivery

packages/ui/src/components/chat/ChatInput.tsx, in handleSubmit:

const [deniedPermissions, dismissedQuestions] = await Promise.all([
    sessionActions.dismissOpenPermissionsForSession(currentSessionId),
    sessionActions.dismissOpenQuestionsForSession(currentSessionId),
]);
if (deniedPermissions || dismissedQuestions) {
    void handleQueueMessage();
    return;
}

The queue fallback ignores delivery === 'steer'. Stale permission/question rows in the client stores (e.g. permissions replied out-of-band, so the client never saw permission.replied) make the dismiss calls return true on ordinary sends, so every Steer on an affected session becomes a server-queue delivery instead. Observable: the message later re-enters the chat via the queue dispatch while the queue block is still rendered — reads as sent twice; or pops in minutes later at run end. Fresh sessions (no blocker history) steer correctly, which confirms the trigger. Suggested fix: when delivery === 'steer', dismiss the blockers but send directly (prompt_async with delivery: "steer"); keep the queue fallback for Queue-mode and non-steer sends. Branch with tested fix available: fix/steer-v1.22.2 — happy to open a PR.

Evidence (single Enter press, 1.22.1): t+0.0s POST /api/message-queue/.../items (rev bump, queue block renders) instead of a send; t+1.1s the dispatch tick delivers it as a fresh user message.

Defect 2 — steer into a tool-executing turn aborts it and strands the prompt

Same model both sides (mimo-v2.5), direct sends, no queue involved:

  • Steer at +10s while a bash tool is executing: in-flight run aborted (MessageAbortedError card) and the steered message is never answered — the session dead-ends (user message, no assistant reply, no new run).
  • Steer at +7s during the reasoning phase: merged cleanly, run continued, answered.

So a prompt steered into a tool-executing turn kills the turn and drops the new prompt on the floor. At minimum the steered prompt must start its turn; ideally the abort card should not read as an error when it is the steer doing the interrupting.

Defect 3 — restored queue item never dispatches on 1.22.2

An item queued pre-restart is restored at boot ([message-queue] restored queues for 1 session(s)) then sits ~45 min on an outwardly idle session (no part updates, dispatcher log silent — no sends, no errors). Expected: the boot-time reconcile tick delivers it once the session is idle.

Workaround

Follow-up behavior Queue, or Stop-then-send. Avoid Steer on 1.22.x for now.

Activity

  1. added
    bugSomething isn't working
    area:chat-inputChat input box, IME, message composing
    area:sessionsSession lifecycle, list, status, history
    regressionBug that worked in a previous release
    on Sep 5, 2026
  2. openchamber-bot commented on Sep 5, 2026

    @openchamber-bot
    Contributor

    For the maintainer: PR #3369 by the same reporter already covers defect 1. Defects 2 and 3 need separate investigation.

    Defect 1 — queue downgrade. The blocking-prompt branch at ChatInput.tsx:1370-1387 ignores delivery === "steer" when it queues after dismissing stale permissions/questions. PR #3369 fixes this correctly: steer clears blockers then sends directly via prompt_async with delivery: "steer". Merge-ready once reviewed.

    Defect 2 — steer aborts tool-executing turn. Steer during a tool phase (e.g. bash execution) hits the runner abort path: session.abort() terminates the in-flight run, surfacing a MessageAbortedError card. The steered message is never dispatched as the next turn — it lands in the chat with no assistant reply. Steer during reasoning merges cleanly because the runner accepts the new content without aborting. Root cause is plausible but unconfirmed for the reporters exact symptom: the runner discards the steered message when the run state transitions to aborted before prompt_async with delivery: "steer" can establish a new turn. This overlaps with #2221 (abort-while-queued stalls) and #3194 (message dropped during busy session), but is a distinct path — steer goes through prompt_async, not the queue dispatcher. Needs upstream input on whether steer should queue the prompt as the next turn rather than aborting, or whether the runner should handle steer-during-tool differently.

    Defect 3 — restored queue stall. The server-side dispatcher at runtime.js:589-593 arms dispatch for each restored queue via reconcileAll() after load(), which calls armDispatch(sessionId, 500ms). The tick() then calls isSessionIdle() which hits /session/status and /session/{id}/message. If the session is already idle at boot, the tick should fire within ~500ms and send. The reporter observes 45 minutes of silence on an idle session, which points to either: (a) the isSessionIdle message tail check returning an unfinished assistant message from a prior run that the session status API does not mark busy, or (b) a race where the restore loads but queues.size === 0 before the write settles. Either way, the server-side queue dispatcher is the right code path — need logs from a failed restore to narrow further.

    Reproduction approach for defect 2

    Steer a prompt during tool execution (not reasoning) on a session with follow-up behavior set to Steer. The abort card appears and the steered message sits unanswered. Reproducing defect 3 requires queuing a message, restarting the server, and checking the dispatcher log for the restored session after boot.

  3. JustinKeltner commented on Sep 5, 2026

    @JustinKeltner
    ContributorAuthor

    Concrete transcript for defect 2 (abort-and-strand)

    Session "Delayed hi after 60 seconds", OpenChamber 1.22.2, mimo-v2.5, steer submitted as a follow-up on a busy run. Delivered directly — no queue item ever existed for this session.

    • 14:02:15 — user: "sleep for 60 seconds then say hi" → assistant run starts, bash tool executes sleep 60 && echo "hi"
    • 14:02:25 — user: "steer-fix-9k2" (stored as user message + text part immediately)
    • 14:02:29 — runner kills the tool. Tool record: status completed, output (no output) + User aborted the command
    • UI shows "OpenCode stopped this reply / MessageAbortedError: Aborted"
    • After that: nothing. No assistant reply, no new run, no further parts or events. The session dead-ends with the steered prompt unanswered.

    Contrast from an identical setup 18 minutes later (same model, same sleep tool): steering 5s into the sleep merged cleanly, the sleep finished, and the reply came back. So the same steer-into-active-turn path folds the prompt sometimes and aborts-then-strands it other times.

  4. JustinKeltner commented on Sep 5, 2026

    @JustinKeltner
    ContributorAuthor

    Defect 2 — third data point: merges mid-MCP-tool on stock 1.22.2

    Same racy steer-into-active-tool path, different outcome again — this time on a toolport (MCP) call, on unmodified 1.22.2 (fix branches not deployed):

    Session "Proxmap -32001 timeout root cause (fork #1)":

    • 15:54:18 → 15:56:20 — toolport_toolport_call_tool executing
    • 15:55:34 — user follow-up submitted as Steer mid-tool → delivered directly (no queue item), user message stored immediately
    • 15:56:37 — run continues with the steered content folded in; answered normally

    Sample set across today's tests, same code path:

    steer landed during outcome
    bash sleep (1.22.1/1.22.2, 14:02) tool killed, run aborted, prompt stranded unanswered
    bash sleep (1.22.2, 14:20) merged cleanly, run continued, answered
    MCP toolport call (1.22.2, 15:55) merged cleanly, run continued, answered

    So the abort-vs-merge outcome is not tool-type-deterministic (bash produced both) and is present on the latest release. Looks like a race between the steered prompt_async and the runner's step boundary.

  5. JustinKeltner commented on Sep 7, 2026

    @JustinKeltner
    ContributorAuthor

    Here's a Loom video of the issue on desktop (happens on all platforms since I think 1.22.1) - https://www.loom.com/share/ab9d39cb126342b3a0873d0a8b58695e

  6. JustinKeltner commented on Sep 9, 2026

    @JustinKeltner
    ContributorAuthor

    Retested 2026-09-09 on a three-role 77042 fleet, all official 1.22.2: queue path healthy (explicit Queue-mode follow-up lands server-side, no toast, run-end flush, single delivery). The downgrade branch is still present in the shipped 1.22.2 bundle — matches the filed code reading; no live Steer-mode sample this round (setting was Queue). No change to the defect-1 claim; #3369 still covers it and is mergeable.

  7. JustinKeltner commented on Sep 9, 2026

    @JustinKeltner
    ContributorAuthor

    Race extended same day, direct prompt_async steers mid-sleep 180: +48s merge, +69s merge, both answered post-tool. Tally abort 1 / merge 4. No upstream change in the path. Step-boundary race stands — a clean steer-into-tool is consistent with the bug, not evidence against it.

  8. btriapitsyn commented on Sep 19, 2026

    @btriapitsyn
    Collaborator

    Could you retest defect 2 on the latest version? We tried sending a Steer follow-up while a foreground subagent was running, and again while a bash tool was running sleep 60. Both completed normally and the follow-up was answered. We haven't reproduced the abort-and-strand behavior in those attempts. If it still happens for you, please share your OpenChamber and OpenCode versions and a fresh recording or transcript. Thanks!

  9. openchamber-bot commented on Oct 18, 2026

    @openchamber-bot
    Contributor

    This issue has been automatically marked as stale because it has not had any activity in the last 28 days. It will be closed in 7 days if no further activity occurs.

  10. yulia-ivashko commented on Oct 18, 2026

    @yulia-ivashko
    Contributor

    Thanks for the thorough report. Defect 1 (Steer silently turned into a queued message) is fixed in #3369 and defect 3 (a restored queue that stalls) in #3371, both released since. We couldn't reproduce defect 2 (abort and strand) on the current version, so we're closing this. If Steer still aborts and leaves the message stranded on the latest version, leave a comment here and we'll reopen it.

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

    area:chat-inputChat input box, IME, message composingarea:sessionsSession lifecycle, list, status, historybugSomething isn't workingregressionBug that worked in a previous releasestale

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions