Naar de inhoud
Foutafhandeling

Foutafhandeling

Een aanvraag die mislukt, geeft een HTTP-statuscode terug en een JSON-body met een fouttype en een bericht. Deze pagina toont elke status, laat de foutbody van elk API-formaat zien en zegt welke fouten het waard zijn om opnieuw te versturen.

De SDK's werpen een foutobject op dat de statuscode en de velden van de body bevat. Deze aanvraag noemt een model dat niet bestaat:

import openai
from openai import OpenAI

client = OpenAI(
    api_key="YOUR_API_KEY",
    base_url="https://api.shannon-ai.com/v1",
)

try:
    client.chat.completions.create(
        model="no-such-model",
        messages=[{"role": "user", "content": "Hello"}],
    )
except openai.APIStatusError as error:
    print(error.status_code)                           # 400
    print(error.type)                                  # invalid_request_error
    print(error.body["message"])                       # unknown model: no-such-model
    print(error.response.headers.get("x-request-id"))  # the id of this request

Ze geeft status 400 en deze body terug:

400 JSON
{
  "error": {
    "type": "invalid_request_error",
    "message": "unknown model: no-such-model"
  }
}

Foutbody

Er zijn twee bodies. /v1/messages antwoordt in het Anthropic-formaat; elk ander endpoint antwoordt in het OpenAI-formaat. In beide staan de details in error.type en error.message, dus één reader volstaat voor alle endpoints.

401 OpenAI-formaat
{
  "error": {
    "type": "authentication_error",
    "message": "Invalid API key",
    "code": "invalid_api_key",
    "param": null
  }
}
401 Anthropic-formaat
{
  "type": "error",
  "error": {
    "type": "authentication_error",
    "message": "Invalid API key"
  }
}
Veld Type Beschrijving
error.type string Het soort fout. Zie Fouttypen hieronder.
error.message string Een zin voor een mens. De teksten in de tabellen hieronder zijn stabiel op hun variabele delen na, weergegeven als <id>, <n> of ….
error.code string | null Aanwezig bij sommige fouten in het OpenAI-formaat: invalid_api_key bij 401, request_too_large bij 413, context_length_exceeded als een gesprek te lang is, anders null of afwezig. Beslis eerst op basis van de status en error.type en behandel code als extra.
error.param null Aanwezig bij dezelfde fouten als code. Altijd null.
type string Alleen in het Anthropic-formaat. Altijd error.

Fouttypen

Type Statussen Beschrijving
invalid_request_error 400, 413, 415, 422 De aanvraag zelf is fout: een veld, de body, het model-id of een input die het model niet accepteert. Wijzig de aanvraag voordat je haar opnieuw verstuurt.
authentication_error 401 De API-sleutel ontbreekt, is onbekend of is ingetrokken.
not_found_error 404 Het pad bestaat niet.
rate_limit_error 429 Het saldo dekt de aanvraag niet, flood protection heeft haar gestopt, of het model is bezet. Het bericht zegt welke van de drie.
api_error 500, 502, 503, 504 De aanvraag was in orde en de fout ligt aan onze kant. Verstuur haar opnieuw.
server_error 500 De aanvraag was in orde en de fout ligt aan onze kant. Verstuur haar opnieuw.

Statuscodes

Status Type Bericht Wanneer
400 invalid_request_error Failed to parse the request body as JSON: … De body is geen geldige JSON.
400 invalid_request_error unknown model: <id> model is geen gepubliceerd id. Op /v1/responses ook als model ontbreekt.
400 invalid_request_error No user message provided Shannon-tiers: de aanvraag bevat geen gebruikerstekst.
400 invalid_request_error <id> does not accept image input Er is een afbeelding verzonden naar een gehost open-weight model zonder afbeeldingen als input.
400 invalid_request_error audio and video input are not supported by any hosted model Er is een audio- of video-onderdeel verzonden naar een gehost open-weight model.
400 invalid_request_error <id> does not accept response_format Er is gestructureerde output gevraagd van een gehost open-weight model dat die niet heeft.
400 invalid_request_error <id> does not accept response_format json_schema; use json_object Er is een JSON-schema verzonden naar een gehost open-weight model dat alleen json_object accepteert.
400 invalid_request_error unknown reasoning effort '<value>'; expected off, low, medium or high De reasoning effort is geen van de vermelde waarden. Gehoste open-weight modellen.
400 invalid_request_error count_tokens is available for the hosted open models; unknown model: <id> Er is tokentelling gevraagd voor een model buiten de gehoste open-weight modellen.
401 authentication_error Missing authentication Er is geen API-sleutel verzonden.
401 authentication_error Invalid API key De sleutel is onbekend, vervangen door een nieuwere of ingetrokken.
404 not_found_error Not Found Het pad bestaat niet, bijvoorbeeld /v1/embeddings.
405 api_error Method Not Allowed Het pad bestaat, maar niet met deze HTTP-methode.
413 invalid_request_error Failed to buffer the request body: … De request-body is groter dan 32 MiB.
415 invalid_request_error Expected request with `Content-Type: application/json` De Content-Type-header ontbreekt of is niet application/json.
422 invalid_request_error Failed to deserialize the JSON body into the target type: … Een verplicht veld ontbreekt, zoals messages, of een veld heeft het verkeerde JSON-type.
429 rate_limit_error Quota exceeded. Upgrade your plan at shannon-ai.com/plan De outputlimiet van de aanvraag is groter dan wat er van je saldo over is.
429 rate_limit_error Too many requests. Retry in <n>s. Flood protection: meer dan 120 aanvragen in één minuut op je account. <n> is het aantal seconden tot de minuut eindigt.
429 rate_limit_error Shannon Coder call quota reached. Upgrade your plan at shannon-ai.com/plan shannon-coder-1 op /v1/chat/completions en /v1/messages: de Shannon Coder-calls van je plan voor het huidige venster van 4 uur zijn op.
429 rate_limit_error Shannon routes are temporarily busy. Please retry. Het model is op dit moment bezet.
500 server_error The model backend failed to answer. Please retry. Het model gaf geen antwoord.
500 server_error An internal error occurred. Please retry. Een interne fout terwijl de aanvraag werd voorbereid.
502 api_error The model backend failed to answer. Please retry. Het model gaf geen antwoord. Shannon 3-familie en gehoste open-weight modellen.
503 api_error Could not verify your quota right now. Please retry. Je saldo kon op dit moment niet worden gelezen.
503 api_error token counting is temporarily unavailable for this model Tokentelling is voor dit model op dit moment niet beschikbaar.
504 api_error upstream timed out Een gehost open-weight model deed er langer over dan de tijdslimiet van een aanvraag die niet wordt gestreamd.

De controles verlopen in deze volgorde: API-sleutel, request-body, model-id, flood protection, saldo. Een aanvraag met een verkeerde sleutel en een verkeerde body geeft daarom 401 terug. Een aanvraag die met een 4xx-status wordt geweigerd, wordt niet gefactureerd.

Saldo en flood protection

Elke aanvraag wordt gelijk behandeld: er zijn geen rate tiers en geen aparte API-quota. Toch kunnen twee dingen 429 als antwoord geven, beide met het type rate_limit_error. Het bericht maakt het onderscheid.

Saldo

Je saldo is de planlimiet van vandaag, die om 00:00 UTC opnieuw begint, en daarna je aangeschafte credit. Chat en API gebruiken hetzelfde saldo.

Elke aanvraag reserveert eerst haar outputlimiet: max_tokens, of max_output_tokens op /v1/responses, 4,096 als je geen van beide meestuurt. Zodra het antwoord compleet is, wordt het gereserveerde bedrag vervangen door wat de aanvraag heeft gebruikt. Als het bedrag niet in het resterende saldo past, geeft de aanvraag Quota exceeded terug voordat het model begint.

Aanvragen die tegelijk lopen, reserveren elk hun eigen bedrag. Veel parallelle aanvragen met een hoge max_tokens kunnen het saldo daarom even opmaken, ook als elk antwoord kort is. Een lagere max_tokens reserveert minder.

Flood protection

Flood protection staat 120 aanvragen per minuut per account toe. Het telt het account, niet de sleutel, over /v1/chat/completions, /v1/responses en /v1/messages samen. De minuut begint met je eerste aanvraag.

Aanvraag nummer 121 binnen die minuut geeft Too many requests. Retry in <n>s. terug en kost niets. Geweigerde aanvragen tellen ook mee, dus een client die zonder te wachten opnieuw verstuurt, blijft geweigerd tot de minuut voorbij is. Wacht de <n> seconden uit het bericht.

Aanvragen die parallel worden verstuurd, worden niet geweigerd omdat ze parallel zijn. Ze wachten in de rij en worden om de beurt beantwoord.

GET /v1/models en de endpoints voor tokentelling worden niet meegeteld.

Meer over limieten en saldo, en waar je je eigen saldo en gebruik ziet: Limieten en saldo Sleutels en gebruik

Wat je opnieuw moet proberen

Verstuur een aanvraag alleen opnieuw als dezelfde aanvraag kan slagen. De OpenAI- en Anthropic-SDK's proberen 429- en 5xx-antwoorden zelf al twee keer opnieuw; stel max_retries (maxRetries in JavaScript) in om dat te wijzigen.

Fout Opnieuw versturen? Hoe
400, 404, 405, 413, 415, 422 Nee. Corrigeer eerst de aanvraag. Het bericht noemt het veld, het model of de input die fout is.
401 Nee. Gebruik een geldige sleutel. Maak de sleutel aan of vervang hem op de pagina Sleutels en gebruik.
429 Too many requests Ja, na het wachten. Wacht het aantal seconden uit het bericht en verstuur dan dezelfde aanvraag.
429 Quota exceeded Niet zoals ze is. Verlaag max_tokens, wacht op de dagelijkse reset om 00:00 UTC, of voeg credit toe.
429 Shannon Coder call quota reached Ja, in het volgende venster. De vensters beginnen elke 4 uur vanaf 00:00 UTC. Een ander model antwoordt direct.
429 … temporarily busy Ja. Wacht een paar seconden, bij elke volgende poging langer.
500, 502, 503 Ja. Wacht 1 seconde, dan 2, 4 en 8. Stop na een paar pogingen en meld het request-id.
504 Ja. Verstuur haar met stream op true: de tijdslimiet geldt voor antwoorden die niet worden gestreamd.

Een retry-lus die deze tabel volgt:

import re
import time

import openai
from openai import OpenAI

# max_retries=0: this loop does the retrying, the SDK does not add its own.
client = OpenAI(api_key="YOUR_API_KEY", base_url="https://api.shannon-ai.com/v1", max_retries=0)


def create_with_retry(attempts=5, **request):
    for attempt in range(attempts):
        try:
            return client.chat.completions.create(**request)
        except openai.RateLimitError as error:
            text = str(error)
            flood = re.search(r"Retry in (\d+)s", text)
            if flood:
                time.sleep(int(flood.group(1)))   # flood protection: wait out the minute
            elif "temporarily busy" in text:
                time.sleep(2 ** attempt)
            else:
                raise                             # balance: a wait of seconds does not help
        except (openai.InternalServerError, openai.APIConnectionError):
            time.sleep(2 ** attempt)              # 1, 2, 4, 8 seconds
    raise RuntimeError("the request failed after all attempts")


response = create_with_retry(
    model="shannon-3",
    messages=[{"role": "user", "content": "Hello"}],
)
print(response.choices[0].message.content)

Fouten binnen een stream

Een stream heeft vanaf zijn eerste byte status 200. Een fout daarna komt binnen als event in de stream: een chunk met een error-lid op /v1/chat/completions, een error-event op /v1/messages, een response.failed- of error-event op /v1/responses. De afsluitende events van de stream volgen nog steeds. Behandel zo'n antwoord als mislukt en verstuur de aanvraag opnieuw, zoals bij een 5xx-status.

Een gesprek dat langer is dan het contextvenster van het model, wordt op deze manier gemeld, met het type invalid_request_error en de code context_length_exceeded. Verkort het gesprek voordat je het opnieuw verstuurt.

De exacte frames worden beschreven bij streaming. Streaming

Request-id's

Elk antwoord, ook bij fouten, heeft een x-request-id-header. Dat is de waarde die je in je eigen x-request-id-header hebt meegestuurd, of 12 hexadecimale tekens als je niets hebt meegestuurd. Log hem en vermeld hem als je hulp vraagt bij een aanvraag.