can1357/oh-my-pi · error · AnthropicConnectionTimeoutError
AnthropicConnectionTimeoutError
Error message
AnthropicConnectionTimeoutError
What it means
AnthropicClient.#fetchOnce sets a timeout timer around its fetch call, aborting the request controller when it fires. If the fetch rejects due to that internal timeout (timedOut flag set) while the caller's own signal was NOT aborted, the client throws AnthropicConnectionTimeoutError. This distinguishes 'the API did not respond within the client's timeout window' from a caller-initiated cancellation.
Source
Thrown at packages/ai/src/providers/anthropic-client.ts:293
): Promise<Response> {
const controller = new AbortController();
let timedOut = false;
const timer = setTimeout(() => {
timedOut = true;
controller.abort();
}, timeoutMs);
const onAbort = () => controller.abort();
callerSignal?.addEventListener("abort", onAbort, { once: true });
try {
return await fetchFn(url, {
...(this.#options.fetchOptions ?? {}),
method: "POST",
headers,
body,
signal: controller.signal,
});
} catch (error) {
if (timedOut && !callerSignal?.aborted) throw new AIError.AnthropicConnectionTimeoutError();
throw error;
} finally {
clearTimeout(timer);
callerSignal?.removeEventListener("abort", onAbort);
}
}
async #backoff(
attempt: number,
responseHeaders: Headers | undefined,
signal: AbortSignal | undefined,
): Promise<void> {
const delayMs = retryDelayFromHeaders(responseHeaders) ?? calculateAnthropicRetryDelayMs(attempt);
try {
await scheduler.wait(delayMs, { signal });
} catch {
throw createAbortError();
}View on GitHub (pinned to 9690622007)
Solutions
- Increase the client's request timeout option to accommodate your largest non-streaming requests
- Use streaming responses so connection/TTFT timeouts don't fire while tokens are still expected
- Retry with backoff — these are transient by nature; combine with a circuit breaker for persistent stalls
- Check whether a proxy/LB in the path silently drops long-lived connections and raise its idle timeout
- Distinguish AnthropicConnectionTimeoutError from AbortError in your catch handling so caller cancellations aren't retried
Example fix
// before: default timeout too small for big prompts
const client = new AnthropicClient(key);
// after: explicit timeout + retry on timeout only
try {
return await client.request(req, { timeoutMs: 120_000 });
} catch (e) {
if (e instanceof AIError.AnthropicConnectionTimeoutError) return retryWithBackoff(req);
throw e;
} Defensive patterns
Strategy: retry
Type guard
import { AIError } from "@oh-my-pi/pi-ai";
function isConnectionTimeout(e: unknown): e is AIError.AnthropicConnectionTimeoutError {
return e instanceof AIError.AnthropicConnectionTimeoutError;
} Try / catch
try {
return await client.request(req);
} catch (e) {
if (isConnectionTimeout(e)) {
// server never responded in time — safe to retry with backoff
return retryWithBackoff(() => client.request(req), { attempts: 3 });
}
throw e; // AbortError (caller cancelled) and others must not be retried
} Prevention
- Size the client timeout to your largest non-streaming request (or use streaming)
- Always distinguish timeout from caller AbortError before retrying
- Alert on timeout rates — a rising trend usually means proxy/LB idle-timeout problems
- Keep retry counts bounded and add jitter to avoid thundering herds
When it happens
Trigger: A request to the Anthropic API exceeds the client's configured timeout: slow/hung TLS negotiation, no response headers from a stalled proxy, or an extremely slow network — after which the internal AbortController fires and fetch rejects with an abort error attributed to the timer.
Common situations: Long non-streaming requests (large prompts) exceeding a tight timeout; requests routed through a hanging corporate proxy; regional network congestion; misconfigured timeout for batch/offline workloads that legitimately take minutes.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- AnthropicConnectionError
- xAI device-code request failed: ${error instanceof Error ? e
- timed out: {command}
- stream ended before message_stop
- xAI device-code token polling failed: ${error instanceof Err
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/f06b78f13b75a730.
Report an issue: GitHub.