Skip to content

QUEUED tag stuck on all user messages when an assistant message has null time.completed #16856

@doomsday616

Description

@doomsday616

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

  1. Start a session and exchange a few messages
  2. Kill the OpenCode process while the assistant is mid-response (e.g. taskkill /f /im opencode.exe or the process crashes)
  3. Restart OpenCode and resume the same session
  4. 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:

  1. Startup/session-load cleanup: When loading a session, scan for assistant messages with time.completed = null and error = null that are not the very last message. Set their time.completed to their time.created (or mark them with an error like OrphanedMessageError).

  2. Smarter pending logic: 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.

  3. 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

Metadata

Metadata

Assignees

Labels

coreAnything pertaining to core functionality of the application (opencode server stuff)

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions