vercel/ai · error · APICallError

${streamError?.message ?? 'OpenAI stream failed before any o

Error message

${streamError?.message ?? 'OpenAI stream failed before any output was generated'}

What it means

The OpenAI provider peeks at the beginning of an SSE stream before handing it to the consumer. If an error frame arrives before any output (e.g. a `response.failed` event or an `error` object), it throws an APICallError whose message is the provider's error frame message, or the fallback 'OpenAI stream failed before any output was generated' when the frame cannot be parsed into a known error shape. This surfaces stream-level API failures (auth, quota, invalid request) synchronously as a throw instead of an empty stream.

Source

Thrown at packages/openai/src/openai-stream-error.ts:110

        return streamForConsumer;
      }

      const chunk = result.value;

      if (!chunk.success) {
        return streamForConsumer;
      }

      const errorFrame = getError(chunk.value);

      if (errorFrame != null) {
        // Let the source finish instead of cancelling its transform pipeline.
        // Node.js 26 can otherwise leave a queued pipe write rejected with
        // the cancellation reason after the API error has already surfaced.
        drainAfterError = true;
        drainReader(reader).catch(() => {});
        drainReader(streamForConsumer.getReader()).catch(() => {});
        throw createOpenAIStreamError({
          frame: errorFrame,
          url,
          requestBodyValues,
          responseHeaders,
        });
      }

      if (isOutputChunk(chunk.value)) {
        return streamForConsumer;
      }

      if (!accepted && isAcceptedChunk?.(chunk.value) === true) {
        accepted = true;
      }
    }
  } finally {
    if (!drainAfterError) {
      reader.cancel().catch(() => {});

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Inspect error.statusCode and error.data on the thrown APICallError: fix credentials for 401, billing/quota for 429 insufficient_quota (not retryable), and request size/params for 400 context_length errors.
  2. Check error.responseBody (the raw JSON error frame) when message is the generic fallback to see the real provider error.
  3. Retry with backoff only when isRetryable is true (408/409/429 rate-limit/5xx); never retry insufficient_quota or 4xx auth errors.
  4. Verify OPENAI_API_KEY, model id, and that the account has access to the requested model before re-running.
  5. Upgrade @ai-sdk/openai if the frame carries a new error shape so parseStreamError can extract the real message/status.
Defensive patterns

Strategy: try-catch

Validate before calling

if (!process.env.OPENAI_API_KEY) throw new Error('OPENAI_API_KEY is not set');
// and pre-check quota/model access out of band before long streaming jobs.

Type guard

import { APICallError } from '@ai-sdk/provider';
function isOpenAIStreamError(e: unknown): e is APICallError & { statusCode: number; data: unknown } {
  return APICallError.isInstance(e);
}

Try / catch

try {
  const result = streamText({ model: openai('gpt-4o'), prompt });
} catch (error) {
  if (APICallError.isInstance(error)) {
    if (error.statusCode === 429 && JSON.stringify(error.data).includes('insufficient_quota')) {
      // billing problem: alert, do not retry
    } else if (error.isRetryable) {
      // retry with backoff
    } else {
      // fix request (400) or credentials (401/403)
    }
  }
  throw error;
}

Prevention

When it happens

Trigger: Calling streamText/streamObject with an OpenAI Responses/Chat model where the server sends an error event before the first token: expired/invalid API key, insufficient_quota, context_length_exceeded, or a malformed request accepted at HTTP level but failing in-stream. The error is thrown from throwIfOpenAIStreamErrorBeforeOutput (called by checkedResponse/checked/promise wrappers).

Common situations: OpenAI account out of credits (insufficient_quota); project key revoked or rotated; model name not accessible to the key; request exceeding context length; transient 429/5xx conditions emitted in-stream after a 200 response header.

Related errors


AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30). Data as JSON: /api/errors/650a89da01c6a24b. Report an issue: GitHub.