Skip to content

Errors

Errors come back with an HTTP status and a JSON body in the format of the endpoint you called, so your SDK raises its usual exceptions:

{ "error": { "message": "Your prepaid balance is used up. Add funds to continue sending requests." } }

The Messages endpoint uses Anthropic's shape, {"type": "error", "error": {"type": "...", "message": "..."}}. The message always says what went wrong and what to do about it.

Status codes

StatusCauseWhat to doRetry?
400The request is invalid: missing model, malformed JSON, an option the model doesn't support.Fix the request.No
401The key is missing, malformed, deleted or rolled.Check the key and header.No
402The balance or the plan credit is used up, or a plan's payment is outstanding.Add funds or wait for the plan to renew; the message says which.After fixing
403The key's workspace can't use this model or endpoint, for example a plan key calling a model the plan doesn't cover.Use a key from a workspace that can.No
404The model isn't offered on this endpoint (the message lists the models that are), the path doesn't exist, or the resource belongs to another project.Check the model ID and endpoint.No
405The method isn't supported on this path.Use the method in the Allow header.No
409An idempotency key was reused, or a resource isn't ready yet.Use a new key for a new request; wait for the resource.Sometimes
413The request body is larger than 64 MiB.Send a URL instead of inline data, or split the input.No
415The body isn't JSON or multipart form data.Set Content-Type.No
429Too many requests, or too many in progress at once.Wait for Retry-After.Yes
500, 502The model failed to complete the request.Retry with backoff.Yes
503A temporary problem, including when your key or balance couldn't be checked. Nothing was sent or charged.Retry shortly.Yes

Requests refused before a model ran — every 4xx above and the 503s — are not charged.

Retrying

Retry 429, 500, 502 and 503 with exponential backoff and jitter, and honour Retry-After when it's present:

async function withRetries(call, attempts = 5) {
  for (let attempt = 0; ; attempt++) {
    try {
      return await call();
    } catch (error) {
      const status = error.status;
      const retryable = status === 429 || status >= 500;
      if (!retryable || attempt + 1 >= attempts) throw error;
      const retryAfter = Number(error.headers?.["retry-after"]);
      const delay = Number.isFinite(retryAfter) && retryAfter > 0
        ? retryAfter * 1000
        : Math.min(30_000, 500 * 2 ** attempt) * (0.5 + Math.random());
      await new Promise((resolve) => setTimeout(resolve, delay));
    }
  }
}

The OpenAI and Anthropic SDKs already retry these statuses a couple of times; raise maxRetries for batch jobs rather than wrapping them again.

Add an Idempotency-Key to requests you retry, so a retry after a network error can never be processed twice.

Errors in a stream

Once a stream has started, an error arrives as an event in the stream, not as an HTTP status. See streaming.

Model errors

When the model itself can't complete a request, the message is a neutral "The model could not complete this request. Please try again." Retry, or try a different model if it keeps happening.