You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
tui: delivered inbox items can retain a pending label #59615
A delivered inbox item can still show as pending when the client misses its delivery event. The client can also retain an optimistic pending item after a successful prompt submission if both inbox events are missed. Pending state should clear for consumed items without removing their message history or genuinely pending inputs.
The live report was observed in a customised downstream build. Its exact event sequence is not known; the steps below reproduce the client-state gap in a fixture, not the historical live sequence.
Related: #56748 describes a delivered image remaining as a queued card, but its trigger differs and a shared cause is unconfirmed.
Plugins
Unavailable for the observed terminal. The client fixture loads no plugins.
OpenCode version
Customised downstream build based on 2.1.4. The fixture uses public source at 59542dae3c882e4cf9b029c83de508fffd797487.
Steps to reproduce
In a mocked client fixture:
Load a synthetic inbox item alongside genuinely pending inputs.
Have the server consume the item but omit its delivery event to the client.
Send an execution failure or success event and inspect the pending collection.
The consumed item remains pending on the pinned public source. Alternatively, submit an optimistic prompt, return a successful POST after consumption and omit both inbox events: the optimistic item remains pending. Three focused tests fail before the proposed change.
Screenshot
Unavailable; no screenshot or recording is included.
Operating System
Linux x86-64.
Terminal
Unavailable; the observed terminal was not captured.
Thanks for the detailed fixture-based report! I think this is a duplicate of #56748. Its symptom differs, but the root cause worked out in the PRs for that issue seems to be the same client-state gap you describe. The optimistic row's outbox guard is only cleared by the inbox echo, an inbox read that finds the item, or a rollback. If the delivery events are missed, a consumed item stays pending. Image prompts in #56748 just widen the window.
Possible duplicates and related items, ordered by likelihood:
Thanks for looking at this. I tested the three focused cases against #58072 at 71c354b. Its new tests pass, but these cases still fail without a message-list refresh or a conflict/cancel action:
reconciles a missed inbox delivery at session.execution.failed while keeping pending inputs and the corresponding session.execution.succeeded case both retain the consumed msg_notice in the pending list.
reconciles a successful local admission when both inbox events were missed retains msg_local after the successful POST and an inbox refresh: expected ["msg_remote"], received ["msg_remote", "msg_local"].
Additional deterministic reproduction on v2.2.7 (fedc6f208aa2bd54c1019227214568083f6380ad): an older inbox hydration response arriving after a fresh transcript response reintroduces an already-consumed item into pending state. This fixture needs no plugins, no optimistic prompt submission and no live delivery event.
This may be useful alongside the missed-event cases above and the stuck-row symptom in #63345. I have reproduced this client race, but have not captured the exact event sequence of the original live TUI occurrence.
Reproduction
In an empty directory, install @opencode/[email protected] and [email protected] with Bun, save the following as race.test.ts, and run bun test race.test.ts. HTTP responses are controlled; the client implementation is the published package.
The local matrix also includes two controls per combination: delivery events clear pending; inbox hydration completing before transcript hydration clears pending. Those 8 controls pass. All 4 stale-inbox cases fail, for user/synthetic inputs and both ID shapes.
The server transcript has the input at time 2 followed by the assistant at time 3. The late inbox response restores enqueue time 1 and marks the delivered input pending. Feeding that state into the unchanged v2.2.7 reduceSessionRows places the input after the assistant. The duplicate assistant ID in this diagnostic list comes from projecting separate assistant rows.
The upstream solid-inbox-race.test.ts baseline separately passed 8/8 in the same environment (Windows, Bun 1.3.12). No product code was changed for this reproduction.
Activity
opencode-agent commentedon Oct 27, 2026
Thanks for the detailed fixture-based report! I think this is a duplicate of #56748. Its symptom differs, but the root cause worked out in the PRs for that issue seems to be the same client-state gap you describe. The optimistic row's
outboxguard is only cleared by the inbox echo, an inbox read that finds the item, or a rollback. If the delivery events are missed, a consumed item stays pending. Image prompts in #56748 just widen the window.Possible duplicates and related items, ordered by likelihood:
409Your three focused tests could be useful on #58072, to check whether it covers both scenarios.
The bot will close this issue as a duplicate in 1 day unless you reply explaining how your problem differs from #56748.
kernel-oops commentedon Oct 27, 2026
Thanks for looking at this. I tested the three focused cases against #58072 at
71c354b. Its new tests pass, but these cases still fail without a message-list refresh or a conflict/cancel action:reconciles a missed inbox delivery at session.execution.failed while keeping pending inputsand the correspondingsession.execution.succeededcase both retain the consumedmsg_noticein the pending list.reconciles a successful local admission when both inbox events were missedretainsmsg_localafter the successful POST and an inbox refresh: expected["msg_remote"], received["msg_remote", "msg_local"].The same three fail on the pinned public base. I cannot establish the original live event sequence, so I cannot rule out overlap with #56748, but these fixture cases are not cleared by #58072's execution or admission paths. The tests and fix are on https://github.com/kernel-oops/opencode/tree/fix/pending-delivery-reconciliation if useful.
Neko-Yukari commentedon Nov 12, 2026
Additional deterministic reproduction on v2.2.7 (
fedc6f208aa2bd54c1019227214568083f6380ad): an older inbox hydration response arriving after a fresh transcript response reintroduces an already-consumed item into pending state. This fixture needs no plugins, no optimistic prompt submission and no live delivery event.This may be useful alongside the missed-event cases above and the stuck-row symptom in #63345. I have reproduced this client race, but have not captured the exact event sequence of the original live TUI occurrence.
Reproduction
In an empty directory, install
@opencode/[email protected]and[email protected]with Bun, save the following asrace.test.ts, and runbun test race.test.ts. HTTP responses are controlled; the client implementation is the published package.Observed results
The local matrix also includes two controls per combination: delivery events clear pending; inbox hydration completing before transcript hydration clears pending. Those 8 controls pass. All 4 stale-inbox cases fail, for user/synthetic inputs and both ID shapes.
Example observed state:
{"type":"user","id":"msg_000000000001normal","clientInputs":["msg_000000000001normal"],"clientTime":1,"rows":["msg_000000000002next","msg_000000000002next","msg_000000000001normal"]}The server transcript has the input at time 2 followed by the assistant at time 3. The late inbox response restores enqueue time 1 and marks the delivered input pending. Feeding that state into the unchanged v2.2.7
reduceSessionRowsplaces the input after the assistant. The duplicate assistant ID in this diagnostic list comes from projecting separate assistant rows.Relevant source
The upstream
solid-inbox-race.test.tsbaseline separately passed 8/8 in the same environment (Windows, Bun 1.3.12). No product code was changed for this reproduction.