Skip to content

Anthropic 5xx errors incorrectly marked non-retryable, stopping agent loop #19394

Closed as not planned

Description

@sigvardt

Bug

When the Anthropic API returns a 500 Internal Server Error via SSE stream, the agent loop stops immediately instead of retrying.

Root Cause

The Vercel AI SDK's Anthropic provider creates APICallError with isRetryable: error.type === 'overloaded_error' for SSE-delivered errors. This means internal_server_error (HTTP 500) is marked isRetryable: false.

In packages/opencode/src/provider/error.ts, parseAPICallError passes this through directly for non-OpenAI providers:

isRetryable: input.providerID.startsWith("openai")
  ? isOpenAiErrorRetryable(input.error)
  : input.error.isRetryable

Then in packages/opencode/src/session/retry.ts (line 65):

if (!error.data.isRetryable) return undefined

Returning undefined means "don't retry", so the processor stores the error and stops the loop.

Impact

Any Anthropic API 500 error kills the agent session. Users see AI_APICallError: Internal server error and the loop halts. This is especially disruptive during periods of API instability.

Note: OpenAI errors are handled separately with isOpenAiErrorRetryable() which correctly retries server errors. Only non-OpenAI providers are affected.

Evidence

From production logs — all 6 occurrences show statusCode: 500, isRetryable: false:

AI_APICallError: Internal server error
url: https://api.anthropic.com/v1/messages
statusCode: 500
isRetryable: false

Suggested Fix

In error.ts, add a server error check that overrides the SDK's isRetryable for any 5xx status:

function isServerError(e: APICallError): boolean {
  return !!e.statusCode && e.statusCode >= 500 && e.statusCode < 600
}

Then in parseAPICallError:

isRetryable: isServerError(input.error) || (
  input.providerID.startsWith("openai")
    ? isOpenAiErrorRetryable(input.error)
    : input.error.isRetryable
)

This ensures ANY 5xx error is retryable regardless of what the upstream SDK reports, matching standard HTTP retry semantics.

Environment

  • OpenCode v1.3.3 (also affects v1.2.27)
  • Model: claude-opus-4-6 via anthropic provider
  • AI SDK: @ai-sdk/anthropic

Activity

  1. added
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on Mar 27, 2026
  2. github-actions commented on Mar 27, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    Please review those issues to see if they cover your case, and consider whether this can be consolidated.

  3. tim-mohrbach-ikigai commented on Apr 14, 2026

    @tim-mohrbach-ikigai

    These two fixes are complementary rather than overlapping:

    Both paths can produce the same symptom (5xx kills the session), but fixing only one still leaves the other unfixed. For example, OpenRouter returns 502s as UnknownError with {"code":502,"message":"Network connection lost.","metadata":{"error_type":"provider_unavailable"}} — even if isRetryable is corrected for APICallError, these errors bypass that code path entirely and need the fromError() classification that PR #19204 provides.

    Related: #22448 documents the OpenRouter-specific gap where code (numeric) and metadata.error_type aren't checked by PR #19204's current JSON fallback either.

  4. removed
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on May 3, 2026
  5. github-actions commented on Jul 5, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions