Skip to content

AI Gateway breaks SDK retry: GatewayInternalServerError not recognized by maxRetries #14216

@shtefcs

Description

@shtefcs

Description

The AI Gateway's error handling converts retryable APICallError instances into GatewayInternalServerError instances before they reach the SDK's retry logic. Since the retry function checks APICallError.isInstance(error), Gateway errors are never retried regardless of the maxRetries setting.

Proof

Ran this in Node.js with the installed packages:

const gateway = require('@ai-sdk/gateway/dist/index.js');

const gErr = new gateway.GatewayInternalServerError({ message: 'test', statusCode: 503 });
const apiCallMarker = Symbol.for('vercel.ai.error.AI_APICallError');

console.log('Has APICallError marker:', apiCallMarker in gErr);  // false
console.log('isRetryable:', gErr.isRetryable);                    // undefined
console.log('statusCode:', gErr.statusCode);                      // 503

The error has the Gateway marker (vercel.ai.gateway.error) but NOT the APICallError marker (vercel.ai.error.AI_APICallError), so maxRetries never activates.

Root cause

In @ai-sdk/gateway, the doStream() and doGenerate() methods catch errors and convert them:

// @ai-sdk/gateway/dist/index.js, line ~875
} catch (error) {
  throw await asGatewayError(error, ...);
}

asGatewayError() (line ~433) takes a retryable APICallError (statusCode 503, isRetryable: true) and converts it to a GatewayInternalServerError which extends GatewayError (NOT APICallError).

The SDK's retry function at ai/dist/internal/index.mjs:1207 then fails:

if (error instanceof Error 
    && APICallError.isInstance(error)      // FALSE for GatewayError
    && error.isRetryable === true          // undefined for GatewayError
    && tryNumber <= maxRetries) {
  // This NEVER executes for Gateway errors
}

Impact

Any application using @ai-sdk/gateway with maxRetries > 0 gets zero retries on transient errors (503, 429). The setting is silently ignored. This affects streamText, generateText, generateObject, and streamObject.

Applications using provider SDKs directly (@ai-sdk/google, @ai-sdk/openai) are not affected because their errors pass through as APICallError.

Expected behavior

Gateway errors with retryable status codes (503, 429, 408) should be retried according to maxRetries.

Possible fixes

  1. Make GatewayError extend APICallError (or carry the marker)
  2. Make GatewayError set isRetryable based on status code
  3. Update the retry function to also check GatewayError.isInstance()
  4. Don't convert retryable APICallError to GatewayError in the catch block

Environment

  • ai: 6.0.141
  • @ai-sdk/gateway: 3.0.83

Metadata

Metadata

Assignees

No one assigned

    Labels

    ai/corecore functions like generateText, streamText, etc. Provider utils, and provider spec.ai/providerrelated to a provider package. Must be assigned together with at least one `provider/*` labelbugSomething isn't working as documentedprovider/gatewayIssues related to the @ai-sdk/gateway providerreproduction provided

    Type

    No type
    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