vercel/ai · error · APICallError
Cannot connect to API: ${cause.message}
Error message
Cannot connect to API: ${cause.message} What it means
postToApi catches fetch exceptions thrown while POSTing a request body (JSON or form data) and rethrows them through handleFetchError as an APICallError: 'Cannot connect to API: <cause.message>' with isRetryable: true. This is the SDK's normalization of transport-level failures — the request never received an HTTP response from the provider endpoint.
Source
Thrown at packages/provider-utils/src/post-to-api.ts:164
});
} catch (error) {
if (error instanceof Error) {
if (isAbortError(error) || APICallError.isInstance(error)) {
throw error;
}
}
throw new APICallError({
message: 'Failed to process successful response',
cause: error,
statusCode: response.status,
url,
responseHeaders,
requestBodyValues: body.values,
});
}
} catch (error) {
throw handleFetchError({ error, url, requestBodyValues: body.values });
}
};
View on GitHub (pinned to 69428b1f8b)
Solutions
- Inspect error.cause for the underlying code and fix accordingly: ECONNREFUSED → endpoint not running; ENOTFOUND → hostname typo; ETIMEDOUT/ECONNRESET → network/firewall/load balancer issue.
- Retry with exponential backoff — handleFetchError marks these isRetryable: true — or enable the SDK's maxRetries option (default 2).
- Verify the provider baseURL (createOpenAI({ baseURL }), Azure deployment URLs) resolves from your runtime.
- Configure proxy/dispatcher (undici ProxyAgent, HTTPS_PROXY) in corporate or containerized environments.
- Increase fetch timeouts for slow gateways (UND_ERR_HEADERS_TIMEOUT/BODY_TIMEOUT) via a custom undici Agent.
Example fix
// before
const openai = createOpenAI({ baseURL: 'http://localhost:8080/v1' });
// after (gateway actually running on 8000)
const openai = createOpenAI({ baseURL: 'http://localhost:8000/v1' });
// plus retry in the call
generateText({ model: openai('gpt-4o'), prompt, maxRetries: 5 }); Defensive patterns
Strategy: retry
Validate before calling
// before the call
const endpoint = new URL(baseURL);
await fetch(endpoint.origin, { method: 'HEAD', signal: AbortSignal.timeout(3000) }).catch(e => { throw new Error(`API endpoint not reachable from this host: ${e.cause?.code ?? e.message}`); }); Type guard
import { APICallError } from '@ai-sdk/provider';
function isPostConnectionError(e: unknown): e is APICallError {
return APICallError.isInstance(e) && e.isRetryable === true && e.message.startsWith('Cannot connect to API:');
} Try / catch
try {
const result = await generateText({ model, prompt, maxRetries: 4 });
} catch (error) {
if (APICallError.isInstance(error) && error.isRetryable && error.message.startsWith('Cannot connect to API:')) {
// inspect error.cause.code: ECONNREFUSED -> service down, ETIMEDOUT -> firewall/timeout
// escalate after exhausting retries
}
throw error;
} Prevention
- Double-check baseURL configuration for self-hosted/Azure/custom gateways before deployment.
- Use maxRetries (SDK built-in exponential backoff) for transient connection failures.
- Ensure gateways (vLLM/LiteLLM/Ollama) are running and health-checked in orchestration configs.
- Configure proxy/TLS setup (ProxyAgent, corporate CAs) in restricted networks.
- Raise undici header/body timeouts for slow or large POST payloads.
When it happens
Trigger: Any provider call that uses postJsonToApi/postFormDataToApi (generateText, streamText, generateObject, embeddings, etc.) when fetch itself throws: connection refused/timeout/reset (ECONNREFUSED, ETIMEDOUT, ECONNRESET, UND_ERR_SOCKET), DNS resolution failure, or body upload interrupted mid-flight.
Common situations: Wrong or unreachable baseURL (self-hosted gateways, Azure resource URL typos); API endpoint down or rate-limited at load balancer level; VPN/proxy required but not configured; container DNS failures; long uploads hitting UND_ERR_HEADERS_TIMEOUT against slow gateways; intermittent network blips in serverless environments.
Related errors
- Cannot connect to API: ${cause.message}
- Video generation timed out after ${timeoutMs}ms.
- BLACK_FOREST_LABS_VIDEO_GENERATION_TIMEOUT
- Transcription request timed out after 60 seconds
- claude-code bridge did not complete WebSocket handshake with
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/22f41ff7a54de93b.
Report an issue: GitHub.