vercel/ai · error · APICallError

${parsedError.value.error}

Error message

${parsedError.value.error}

What it means

In doStream, if the initial response stream yields an error payload, the SDK reads the body and safeParseJSON-validates it against xaiStreamErrorSchema. When parsing succeeds, the parsed error string becomes an APICallError (statusCode 200, since the SSE/HTTP layer succeeded). This is xAI reporting an error inside an otherwise successful response stream.

Source

Thrown at packages/xai/src/xai-chat-language-model.ts:399

    const { responseHeaders, value: response } = await postJsonToApi({
      url,
      headers: combineHeaders(this.config.headers?.(), options.headers),
      body,
      failedResponseHandler: xaiFailedResponseHandler,
      successfulResponseHandler: async ({ response }) => {
        const responseHeaders = extractResponseHeaders(response);
        const contentType = response.headers.get('content-type');

        if (contentType?.includes('application/json')) {
          const responseBody = await response.text();
          const parsedError = await safeParseJSON({
            text: responseBody,
            schema: xaiStreamErrorSchema,
          });

          if (parsedError.success) {
            throw new APICallError({
              message: parsedError.value.error,
              url,
              requestBodyValues: body,
              statusCode: 200,
              responseHeaders,
              responseBody,
              isRetryable:
                parsedError.value.code ===
                'The service is currently unavailable',
            });
          }

          throw new APICallError({
            message: 'Invalid JSON response',
            url,
            requestBodyValues: body,
            statusCode: 200,
            responseHeaders,

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Catch the APICallError and retry with backoff, especially if the code is 'The service is currently unavailable' (the SDK marks that retryable)
  2. Reduce request concurrency/rate to avoid mid-stream throttling
  3. Inspect responseBody in the error for xAI's full error detail and adjust the prompt if policy-related

Example fix

// before
const result = await streamText({ model: xai('grok-4'), prompt });
// after
const result = streamText({ model: xai('grok-4'), prompt, maxRetries: 3 });
try {
  for await (const part of result.fullStream) { /* ... */ }
} catch (e) {
  if (APICallError.isInstance(e)) console.error(e.message, e.responseBody);
}
Defensive patterns

Strategy: retry

Validate before calling

null

Type guard

null

Try / catch

import { APICallError } from 'ai';
try {
  const result = streamText({ model, prompt, maxRetries: 3 });
  for await (const part of result.fullStream) { /* ... */ }
} catch (e) {
  if (APICallError.isInstance(e) && e.isRetryable) {
    // SDK already retries for 'The service is currently unavailable'; add outer backoff otherwise
  }
}

Prevention

When it happens

Trigger: Starting a chat completion stream that xAI accepts (HTTP 200) but then emits an error event/body — rate limits applied mid-stream, model overloaded messages, content policy violations detected during generation.

Common situations: High-concurrency streaming workloads hitting mid-stream overload ('The service is currently unavailable'); policy-triggered stream aborts; upstream xAI incidents.

Related errors


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