Skip to content

Retry unexpected MessageAbortedError instead of stopping the session #17717

Description

@dzianisv

Problem

OpenCode can stop a session after a provider-side abort even when the user did not cancel the run.

In the incident we investigated, an assistant message sat for ~16 minutes, produced zero tokens / zero parts, and then completed with:

  • MessageAbortedError
  • message: \"The operation was aborted.\"

The last tool call had already completed successfully. The next model call never returned any content, then the session stopped instead of retrying.

Actual behavior

When SessionProcessor catches a DOMException / AbortError, MessageV2.fromError() converts it into MessageAbortedError.

SessionRetry.retryable() does not treat that error as retryable, so the processor:

  • sets assistantMessage.error
  • publishes the error
  • returns \"stop\"

This makes the session appear stuck/cancelled even though the user did not explicitly cancel it.

Expected behavior

If the session's own abort signal was not triggered, an unexpected AbortError from the model/provider layer should be treated as transient and retried with the normal retry/backoff flow.

A user-initiated cancel should still stop immediately and remain non-retryable.

Root cause

Current logic treats all AbortErrors as equivalent:

  • user cancellation via SessionPrompt.cancel()
  • provider/client/network aborts while waiting for streamed output

Those cases need to be separated.

Proposed fix

  • detect MessageAbortedError in SessionProcessor
  • if input.abort.aborted === false, classify it as retryable and use the existing retry/backoff status flow
  • if input.abort.aborted === true, keep the current cancel behavior
  • add tests covering both cases

Acceptance criteria

  • unexpected AbortErrors retry automatically instead of stopping the session
  • explicit session cancellation still stops immediately
  • retry status is surfaced through existing SessionStatus retry flow
  • tests cover both retryable and non-retryable abort cases

Metadata

Metadata

Assignees

Labels

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

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions