Skip to main content
Start with the HTTP status and error details. Invalid inputs, credentials, and exhausted credits need a change before you retry. Rate limits, temporary service failures, and connection problems may recover after a wait.

Read an API error

Direct HTTP chat-completion requests return structured errors in this form. For example, an unsupported tool_choice produces HTTP 400:
Use message to diagnose the problem, param to locate an offending field, and type or code to classify it when available. Those last three fields can be null; not every validation failure has a dedicated code. Branch on a documented code rather than matching the wording of a message. A connection failure has no HTTP response, and malformed HTTP requests or intermediary failures may not have this JSON body. Record the response’s x-trace-id header when present. It helps support locate the request, but may be absent when a request fails before reaching the API. Also retain the UTC time, endpoint, model, HTTP status, and error details. Keep API keys out of logs and support messages. The SDK exposes errors as SDKError subclasses with status_code, error_type, code, param, request_id, and retry_after. Some typed-argument checks, such as unsupported tool_choice, raise BadRequestError before sending HTTP; those errors have no HTTP status or request ID. For a RateLimitError, code is "rate_limit" and the server’s original code is in details["code"] when present. Exhausted credits raise QuotaExceededError.

Decide whether to retry

Organization rate-limit responses include Retry-After in seconds. An HTTP 503 with code: "model_overloaded" includes Retry-After: 30. Other failures may omit that header; use backoff when it is absent. A retry is a new model request and may produce a different answer or additional usage.

Correct common request problems

Context and output limits

context_length_exceeded means the input or requested completion does not fit the model’s context. Shorten conversation history, reduce the amount of media, or lower max_completion_tokens when the requested output is the problem. Keep enough room for reasoning and the final answer. See the model card for current context and output limits. Exceeding a configured output limit can also produce a validation error without this code. Increasing a client timeout will not fix either request-size problem. A response that starts successfully but ends with finish_reason: "length" is a separate case: handle it as incomplete output.

Images, videos, audio, and files

Check that a media URL is reachable and has not expired, that the bytes decode as the declared format, and that a file reference exists in the organization making the request. An image URL that serves an HTML login page is not an image. For uploads, send the actual media bytes with a matching content type; renaming the extension does not convert a file. Use the Files guide for upload formats and limits, and video understanding for video URLs and frame inputs. When a request contains many media parts, reduce their number; uploading them first does not remove request-level media limits.

Audio input and video soundtracks

An over-limit chat request returns HTTP 400 with type: "invalid_request_error" and code: "audio_token_limit_exceeded"; param can be null. Audio is rejected rather than silently truncated. This validation happens before generation, so a streaming request can also fail with an ordinary JSON error before any SSE events arrive. No soundtrack, or no soundtrack overlap with the processed video window, falls back to frames only. Decode failures and over-limit soundtracks still return errors. See Audio for valid content parts and video soundtracks for the opt-in flag.

Reasoning effort

reasoning_effort accepts exactly none, minimal, low, medium, and high. In a direct HTTP request, an unknown value returns HTTP 400 with invalid_request_error and a parse-error message naming the field. The SDK rejects an invalid typed argument before HTTP with BadRequestError(code="invalid_reasoning_effort"). Correct the value before retrying. Chat completions and Multilook take this field at the top level; Detect uses config.reasoning_effort. A completed HTTP request with reasoning but an empty answer may have exhausted its output budget. Check finish_reason; if it is length, allow more tokens for reasoning and the answer, or use none if reasoning is unnecessary. See Reasoning.

Function-calling requests

The function-calling guide shows how to preserve assistant calls, reasoning, and matching tool results.

Retry a transient inference failure

This example uses the Perceptron SDK and adds an application retry policy. It makes up to three attempts and waits no more than 60 seconds between attempts. If the server asks for a longer wait, it returns the error to the caller instead of retrying early. The request timeout applies separately to each attempt. Install perceptron>=0.4.0, set PERCEPTRON_API_KEY, and save this as retry_example.py:
Run python retry_example.py. The helper retries only the inference request. It does not automatically retry an incomplete answer, rerun application functions, or restart a whole agent workflow. Use the workflow budget guidance when several requests and tool executions share a deadline.

Handle incomplete responses and streams

HTTP 200 means the request was accepted; check the completion as well:
  • finish_reason: "stop" marks a completed answer.
  • finish_reason: "tool_calls" marks a completed model turn asking your application to handle calls.
  • finish_reason: "length" means the output budget was exhausted. Keep any partial text clearly marked as incomplete; do not execute partial arguments or treat truncated JSON or annotations as validated output.
A stream can fail after its HTTP headers have been sent. In that case the API sends an SSE data event containing {"error": {...}} and closes without [DONE]. The Perceptron SDK raises an SDKError subclass for that error event, and IncompleteStreamError when the stream ends without [DONE]. A raw SSE consumer must recognize the error event itself. A dropped connection or stream ending without a finish reason is also incomplete. Keep consuming after the finish chunk so you receive any trailing usage or error event. Do not splice a fresh retry onto an old partial stream. See the tool-call streaming example, tracking stream example, and structured-output validation.

Handle Multilook partial failures

A successful Multilook request can return HTTP 200 while individual entries in results contain an error. Inspect each result before accessing its completions. The prompt error has a message and may include type and code. Keep successful results, and decide whether each failed prompt needs correction or a retry. Resubmit only the prompts you choose to retry, preserving their shared context and any prompt-specific media. Track their original indices in your application: prompt_index in the new response refers to the new request. Also check each returned completion’s finish_reason; truncated output is not necessarily a prompt-level error. For example, a prompt-specific audio input can produce results[].error.code: "audio_token_limit_exceeded" while another prompt succeeds. Request-level validation, such as an invalid reasoning_effort, rejects the whole request before prompt processing. If every prompt fails, the API returns a whole-request error instead of a successful results body. Its status is classified from the first prompt error; unclassified failures return HTTP 502.

Separate tool failures from API failures

A database timeout or failed lookup inside your application is a tool execution failure. Return an explicit error result with the original tool_call_id if you want the model to continue; the tool-agent guide shows the message shape. Keep the assistant calls and completed tool results when retrying the next model request. Do not restart the whole tool loop blindly: a function that sends a message, creates a record, or changes an external system may already have succeeded. Decide how to reconcile or deduplicate that action in your application before repeating it.