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
- 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.
- Check error.responseBody (the raw JSON error frame) when message is the generic fallback to see the real provider error.
- Retry with backoff only when isRetryable is true (408/409/429 rate-limit/5xx); never retry insufficient_quota or 4xx auth errors.
- Verify OPENAI_API_KEY, model id, and that the account has access to the requested model before re-running.
- 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
- Validate API keys and billing status before launching streaming workloads.
- Check error.isRetryable before retrying; never retry insufficient_quota.
- Set up quota/budget alerts on the OpenAI account.
- Log error.data and error.responseBody to capture the raw provider error frame for diagnosis.
- Keep @ai-sdk/openai updated so new provider error shapes are parsed into meaningful messages.
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
- non-streaming transcription with ${this.modelId}
- streaming transcription with ${this.modelId}
- Invalid argument for parameter requests: request IDs must be
- 'element streams in no-schema mode' functionality not suppor
- 'element streams in object mode' functionality not supported
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/650a89da01c6a24b.
Report an issue: GitHub.