Description
Session errors wrapped as UnknownError are never retried, causing the entire conversation to terminate on transient failures.
The retry logic in SessionRetry.retryable() uses a whitelist approach — only explicitly recognized errors (APIError with isRetryable: true, rate limit keywords, etc.) are retried. Everything else, including new provider error formats, unexpected network issues, and unclassified transient errors, falls through to UnknownError and terminates the session.
Current behavior: retryable() returns undefined for UnknownError → no retry → session dies.
Expected behavior: Unknown errors should be retried with a small cap (e.g. 2 attempts). The cost of retrying a permanent error is seconds; the cost of not retrying a transient error is losing the entire conversation context.
Key files:
packages/opencode/src/session/retry.ts — retryable() function defaults to no-retry
packages/opencode/src/session/processor.ts — halt() publishes error and sets status to idle without retry
Description
Session errors wrapped as
UnknownErrorare never retried, causing the entire conversation to terminate on transient failures.The retry logic in
SessionRetry.retryable()uses a whitelist approach — only explicitly recognized errors (APIError withisRetryable: true, rate limit keywords, etc.) are retried. Everything else, including new provider error formats, unexpected network issues, and unclassified transient errors, falls through toUnknownErrorand terminates the session.Current behavior:
retryable()returnsundefinedfor UnknownError → no retry → session dies.Expected behavior: Unknown errors should be retried with a small cap (e.g. 2 attempts). The cost of retrying a permanent error is seconds; the cost of not retrying a transient error is losing the entire conversation context.
Key files:
packages/opencode/src/session/retry.ts—retryable()function defaults to no-retrypackages/opencode/src/session/processor.ts—halt()publishes error and sets status to idle without retry