vercel/ai · error · APICallError

Cannot connect to API: ${cause.message}

Error message

Cannot connect to API: ${cause.message}

What it means

getFromApi wraps low-level fetch failures (TypeError 'fetch failed' / 'failed to fetch' with a cause, or network errors with codes like ECONNREFUSED, ETIMEDOUT, UND_ERR_CONNECT_TIMEOUT) into an APICallError with message 'Cannot connect to API: <cause>' and isRetryable: true. It means the SDK could not establish a connection to the provider URL at all — no HTTP response was received.

Source

Thrown at packages/provider-utils/src/get-from-api.ts:152

      });
    } 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: {},
      });
    }
  } catch (error) {
    throw handleFetchError({ error, url, requestBodyValues: {} });
  }
};

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Read error.cause (the original network error) for the specific code: ECONNREFUSED means the host/port is down; ENOTFOUND means DNS; certificate errors mean TLS interception.
  2. Verify network reachability: curl the same URL from the same machine/container to isolate SDK vs environment.
  3. Configure proxy support (undici ProxyAgent / global dispatcher with HTTPS_PROXY) behind corporate firewalls.
  4. Check DNS/IPv6 issues in Docker by forcing IPv4 (NODE_OPTIONS='--dns-result-order=ipv4first' or Node >=20 default).
  5. Implement retry with backoff — the error is flagged isRetryable: true — for transient connection drops.

Example fix

// before (no proxy config in corp network)
const provider = createOpenAI();
// after
import { ProxyAgent, setGlobalDispatcher } from 'undici';
if (process.env.HTTPS_PROXY) {
  setGlobalDispatcher(new ProxyAgent(process.env.HTTPS_PROXY));
}
const provider = createOpenAI();
Defensive patterns

Strategy: retry

Validate before calling

// before the call
const url = new URL(targetUrl);
await fetch(url.origin + '/health', { signal: AbortSignal.timeout(3000) }).catch(e => { throw new Error(`Endpoint unreachable: ${e.cause?.code ?? e.message}`); });

Type guard

import { APICallError } from '@ai-sdk/provider';
function isConnectionError(e: unknown): e is APICallError {
  return APICallError.isInstance(e) && e.message.startsWith('Cannot connect to API:');
}

Try / catch

try {
  const { value } = await getFromApi({ url, successfulResponseHandler });
} catch (error) {
  if (APICallError.isInstance(error) && error.message.startsWith('Cannot connect to API:') && error.isRetryable) {
    // exponential backoff retry; after N attempts check network/proxy/DNS
  }
  throw error;
}

Prevention

When it happens

Trigger: Any getFromApi call (e.g. provider downloads of images/audio/files, polling URLs) where fetch throws: DNS failure, server unreachable, proxy blocking egress, IPv6/IPv4 issues in Node 18+ undici, TLS interception, or the process lacking network access.

Common situations: Corporate proxy/firewall without HTTPS_PROXY configuration; offline CI runners; wrong baseURL pointing at a non-existent host; self-hosted gateway (e.g. LiteLLM/vLLM) not started; Node 18+ undici preferring IPv6 in Docker containers; missing root CA in corporate environments.

Related errors


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