{"record":{"id":"650a89da01c6a24b","repo":"vercel/ai","slug":"streamerror-message-openai-stream-failed-be","errorCode":null,"errorMessage":"${streamError?.message ?? 'OpenAI stream failed before any output was generated'}","messagePattern":"\\$\\{streamError\\?\\.message \\?\\? 'OpenAI stream failed before any output was generated'\\}","errorType":"exception","errorClass":"APICallError","httpStatus":500,"severity":"error","filePath":"packages/openai/src/openai-stream-error.ts","lineNumber":110,"sourceCode":"        return streamForConsumer;\n      }\n\n      const chunk = result.value;\n\n      if (!chunk.success) {\n        return streamForConsumer;\n      }\n\n      const errorFrame = getError(chunk.value);\n\n      if (errorFrame != null) {\n        // Let the source finish instead of cancelling its transform pipeline.\n        // Node.js 26 can otherwise leave a queued pipe write rejected with\n        // the cancellation reason after the API error has already surfaced.\n        drainAfterError = true;\n        drainReader(reader).catch(() => {});\n        drainReader(streamForConsumer.getReader()).catch(() => {});\n        throw createOpenAIStreamError({\n          frame: errorFrame,\n          url,\n          requestBodyValues,\n          responseHeaders,\n        });\n      }\n\n      if (isOutputChunk(chunk.value)) {\n        return streamForConsumer;\n      }\n\n      if (!accepted && isAcceptedChunk?.(chunk.value) === true) {\n        accepted = true;\n      }\n    }\n  } finally {\n    if (!drainAfterError) {\n      reader.cancel().catch(() => {});","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/openai/src/openai-stream-error.ts#L92-L128","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if (!process.env.OPENAI_API_KEY) throw new Error('OPENAI_API_KEY is not set');\n// and pre-check quota/model access out of band before long streaming jobs.","typeGuard":"import { APICallError } from '@ai-sdk/provider';\nfunction isOpenAIStreamError(e: unknown): e is APICallError & { statusCode: number; data: unknown } {\n  return APICallError.isInstance(e);\n}","tryCatchPattern":"try {\n  const result = streamText({ model: openai('gpt-4o'), prompt });\n} catch (error) {\n  if (APICallError.isInstance(error)) {\n    if (error.statusCode === 429 && JSON.stringify(error.data).includes('insufficient_quota')) {\n      // billing problem: alert, do not retry\n    } else if (error.isRetryable) {\n      // retry with backoff\n    } else {\n      // fix request (400) or credentials (401/403)\n    }\n  }\n  throw error;\n}","preventionTips":["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."],"tags":["openai","api-error","streaming","quota","authentication"],"backgroundTag":"stream-error-before-output","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}