error.code, not on the HTTP status or the message text.
request_id is present on chat completion, Responses and embeddings errors and is also sent as the X-Request-ID header. Keep it: support uses it to look up a single call. The console’s Usage page always shows totals and charts; the per-request list is off by default for customer accounts, so quote the request ID to support@omnirelay.ai when you need one call checked.
For request parameter errors, optional error.param identifies the rejected field, for example temperature or reasoning.effort. It contains no parameter value. Check both the field capability and its combination with the selected reasoning effort. Responses reports native field names. Local budget/protocol validation happens before dispatch. When the provider rejects the request with HTTP 400 or 422, the hold is released and nothing is charged; a recognized code and safe field path are returned, otherwise invalid_parameter. Some models ignore unsupported fields instead of rejecting them; such calls succeed without error.param.
error object in a final data: event (Chat Completions) or an error event with code and message (Responses), and does not end with [DONE].
Error codes
Provider errors (upstream_*)
These codes mean the call reached the model provider and something went wrong there. Whether anything was charged depends on whether model output had already reached you:
- Nothing was delivered: the reservation is released at once and nothing is charged. This is always the case for a non-streamed call, and for a stream that fails before its first output.
- Output was already delivered (a stream that breaks midway), or the provider’s answer arrived but could not be verified: the call is held for review and settled from the provider’s usage record. Do not resend it automatically; contact support with the request ID if the hold does not clear.
An image call that runs longer than about 25 seconds answers
200 before it finishes, so any of these errors can also arrive as the JSON body of a 200 response. Check the parsed body for error first.
upstream_rate_limited (429) is listed above: it is a refusal before processing and is never charged.
Retry guidance
For live inference, an HTTP status alone does not prove that nothing was billed, so disable automatic SDK retries and decide fromerror.code:
- Codes documented as not charged (all 4xx refusals,
upstream_rejected,channel_unavailable,runtime_maintenance) can be retried. Use backoff forrate_limited,concurrency_limitedandupstream_rate_limited. upstream_transport_error,upstream_timeoutand the stream codes are not charged for a non-streamed call or a stream that delivered nothing; retry those.- For codes held for review, or a stream that broke after delivering output, do not resend automatically. Check your balance and contact support with the request ID if you need the outcome confirmed.
Python