-
Notifications
You must be signed in to change notification settings - Fork 12.4k
Description
Observed behavior
When a session contains an assistant message whose time.completed is permanently null (e.g. due to the process being killed mid-response), all subsequent user messages display the QUEUED badge permanently while the session is idle.
When the assistant starts generating a new response, the QUEUED badges disappear (because pending now points to the new in-progress message). Once the response completes, the badges reappear.
Restarting OpenCode does not fix the issue — the orphaned message persists in the database.
Root cause
In packages/opencode/src/cli/cmd/tui/routes/session/index.tsx:
const pending = createMemo(() => {
return messages().findLast((x) => x.role === "assistant" && !x.time.completed)?.id
})
const queued = createMemo(() => props.pending && props.message.id > props.pending)pending finds the last assistant message with no time.completed. If that message is an orphan (created but never completed, no error recorded), pending permanently points to it. Every user message with a higher ID than this orphan is then marked as queued.
Steps to reproduce
- Start a session and exchange a few messages
- Kill the OpenCode process while the assistant is mid-response (e.g.
taskkill /f /im opencode.exeor the process crashes) - Restart OpenCode and resume the same session
- Continue chatting — all new user messages display the QUEUED badge when the assistant is idle
Database evidence
The orphaned message in my session:
id: msg_cd639a895002ewT3VGAPtxafso
role: assistant
time: {"created": 1773120628885} ← no "completed" field
finish: null
error: null
All other assistant messages in the session have time.completed set.
Suggested fix
A few options:
-
Startup/session-load cleanup: When loading a session, scan for assistant messages with
time.completed = nullanderror = nullthat are not the very last message. Set theirtime.completedto theirtime.created(or mark them with an error likeOrphanedMessageError). -
Smarter
pendinglogic: Instead of scanning all messages, only consider the very last assistant message. An orphaned message buried in the middle of conversation history should not affect the queued state of later messages. -
Graceful shutdown handling: On process exit/crash, finalize any in-progress assistant messages so they don't remain in a limbo state.
Environment
- OpenCode v1.2.21
- Windows 11 (cmd.exe shell)
- The crash was caused by running a sync script that kills OpenCode processes as part of its workflow