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
Completed aborted assistant message with zero parts renders as blank/stuck in web UI #17895
When an assistant turn is aborted before it emits any parts, OpenCode can persist a completed assistant message with MessageAbortedError and zero parts.
The backend already considers that turn finished, but the web UI has almost nothing to render for it, so the session can look blank or stuck even though it is no longer running.
This is a different shape from:
#17680 stale thinking state after interruption/restart
#15267 teardown race creating an empty continuation turn
This issue is specifically about the persisted message shape:
assistant message exists
time.completed is set
error.name = MessageAbortedError
parts.length = 0
Concrete evidence
Live session investigated:
session: ses_30ad0ece4ffegDiKt3ugw5wurA
final assistant message: msg_cf98d282b0019d4mnTo0zcQl7H
orphan assistant rows with time.completed IS NULL: 0
pending/running tool parts: 0
So the backend state is not "still running". It is a completed aborted shell.
Why this is bad
The current UI path already treats MessageAbortedError specially, but when the assistant turn has zero visible parts, there is no substantive assistant content to show.
That makes the turn look blank or stuck, even though the backend has already finalized it.
Also, the persisted aborted error currently loses provenance. "The operation was aborted." does not tell us whether the source was:
server restart
user cancel
client disconnect
timeout
some other abort path
Proposed fix
1. Persist abort provenance
Extend MessageAbortedError payload to include an optional structured source, for example:
server_restart
user_cancel
client_disconnect
timeout
unknown
Populate it at the abort sites and in restart recovery.
2. Render zero-part aborted assistant turns explicitly in the web UI
If an assistant turn is:
completed
aborted (MessageAbortedError)
and has zero visible parts
then render a compact interruption card/banner from the error payload instead of effectively showing an empty assistant shell.
3. Add a narrow invariant log
Log only when an assistant message is finalized with:
error != null
time.completed != null
zero visible parts
This keeps diagnostics cheap and focused.
Acceptance criteria
A completed aborted assistant message with zero parts no longer appears blank/stuck in the web UI.
The UI shows a clear interrupted/aborted state for that turn.
MessageAbortedError can carry structured provenance for future diagnosis.
PR #17909 covers the persisted/rendered empty-aborted-turn visibility issue so these sessions stop looking blank/stuck in the UI. The fork PR keeps the runtime retry scoped to empty aborts only.
Activity
fix(session): surface empty aborted turns (anomalyco#17895)
fix(ui): align empty abort visibility (anomalyco#17895)
dzianisv commentedon Mar 17, 2026
Fork and upstream work are now split cleanly:
PR #17909 covers the persisted/rendered empty-aborted-turn visibility issue so these sessions stop looking blank/stuck in the UI. The fork PR keeps the runtime retry scoped to empty aborts only.
fix(session): surface empty aborted turns (anomalyco#17895)
fix(ui): align empty abort visibility (anomalyco#17895)
github-actions commentedon Jul 3, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.