Skip to Content
Model GuideErrors, timeouts and retries

Errors, timeouts and retries

First identify whether a failure comes from authentication, request format, account limits, the selected model, or the network. Repeating the same invalid request does not fix it. Exact error envelopes are documented in the API error reference.

Decide what to retry

Status or conditionRecommended action
400Correct parameters, protocol, model capability or input size
401Check credentials and conflicting authentication settings
403Check access or policy restrictions; do not bypass them
404Verify the assembled endpoint and exact model ID
402 or quota exhaustedCheck credit or limits before another request
429Inspect the error and optional retry guidance; reduce concurrency
408, connection reset or timeoutOutcome may be unknown; check replay safety before retrying
5xxA bounded retry may be appropriate; avoid retry storms

A bounded non-streaming example

This Python example deliberately retries only selected HTTP status failures on a simple text request. It disables SDK retries so attempts do not multiply. Install openai, set FENNO_API_KEY and FENNO_MODEL, then run:

import os from openai import OpenAI client = OpenAI( base_url="https://api.fenno.ai/v1", api_key=os.environ["FENNO_API_KEY"], timeout=60.0, max_retries=0, ) import random import time from datetime import datetime, timezone from email.utils import parsedate_to_datetime from openai import APIStatusError def retry_delay(value, attempt): if value: try: return max(0.0, float(value)) except ValueError: try: date = parsedate_to_datetime(value) return max(0.0, (date - datetime.now(timezone.utc)).total_seconds()) except (TypeError, ValueError, OverflowError): pass return min(2 ** attempt, 8) * random.uniform(0.5, 1.0) deadline = time.monotonic() + 60 for attempt in range(3): remaining = deadline - time.monotonic() if remaining <= 0: raise TimeoutError("Application deadline exceeded") try: response = client.with_options(timeout=min(remaining, 20)).chat.completions.create( model=os.environ["FENNO_MODEL"], messages=[{"role": "user", "content": "Reply with OK."}], ) print(response.choices[0].message.content) break except APIStatusError as error: if error.status_code not in {429, 500, 502, 503, 504} or attempt == 2: raise wait = retry_delay(error.response.headers.get("retry-after"), attempt) if wait > 30 or wait >= deadline - time.monotonic(): raise time.sleep(wait)

The time budget bounds application-level attempts and waits; a transport timeout is not a strict wall-clock guarantee. Connection errors and ambiguous timeouts intentionally propagate instead of being retried automatically. Even a failed generation may have consumed usage; decide whether replay is acceptable for your application.

Streaming and side effects

After output has reached the user, do not silently restart and append a new generation. After a tool has performed a side effect, do not replay it merely because the model response was interrupted. Use explicit confirmation and application-level deduplication.

Treat response.incomplete, an unfinished Messages block, or a stream without its protocol completion signal as partial rather than successful. See streaming.

Diagnose before escalating

  1. Reproduce with a small non-sensitive input and the correct protocol endpoint.
  2. Check the exact model ID and assembled URL; OpenAI clients normally include /v1 in the base URL, while native Anthropic and Gemini clients use the host.
  3. Compare client, application, proxy and upstream timeout settings.
  4. Record timestamp, endpoint, model, status, sanitized error code and request ID when provided.
  5. Contact support without attaching API keys, authorization headers or private prompts to a public issue.

See authentication, rate limits, and cost management.