Felhantering
En begäran som misslyckas returnerar en HTTP-statuskod och en JSON-kropp med en feltyp och ett meddelande. Den här sidan listar varje status, visar felkroppen i varje API-format och anger vilka fel som är värda att skicka igen.
SDK:erna kastar ett felobjekt som bär statuskoden och kroppens fält. Den här begäran anger en modell som inte finns:
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 import OpenAI from "openai";
const client = new OpenAI({
apiKey: "YOUR_API_KEY",
baseURL: "https://api.shannon-ai.com/v1",
});
try {
await client.chat.completions.create({
model: "no-such-model",
messages: [{ role: "user", content: "Hello" }],
});
} catch (error) {
if (!(error instanceof OpenAI.APIError)) throw error;
console.log(error.status); // 400
console.log(error.type); // invalid_request_error
console.log(error.error.message); // unknown model: no-such-model
} curl -i https://api.shannon-ai.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "no-such-model",
"messages": [{"role": "user", "content": "Hello"}]
}' Den returnerar status 400 och den här kroppen:
{
"error": {
"type": "invalid_request_error",
"message": "unknown model: no-such-model"
}
} Felkropp
Det finns två kroppar. /v1/messages svarar i Anthropic-formatet; alla andra endpoints svarar i OpenAI-formatet. I båda finns detaljerna i error.type och error.message, så en enda läsare räcker för alla endpoints.
{
"error": {
"type": "authentication_error",
"message": "Invalid API key",
"code": "invalid_api_key",
"param": null
}
} {
"type": "error",
"error": {
"type": "authentication_error",
"message": "Invalid API key"
}
} | Fält | Typ | Beskrivning |
|---|---|---|
error.type | string | Typen av fel. Se Feltyper nedan. |
error.message | string | En mening för en människa. Texterna i tabellerna nedan är stabila utom i sina variabla delar, som visas som <id>, <n> eller …. |
error.code | string | null | Finns på vissa fel i OpenAI-formatet: invalid_api_key med 401, request_too_large med 413, context_length_exceeded när en konversation är för lång, annars null eller saknas. Avgör utifrån status och error.type först och behandla code som ett tillägg. |
error.param | null | Finns på samma fel som code. Alltid null. |
type | string | Endast Anthropic-formatet. Alltid error. |
Feltyper
| Typ | Statusar | Beskrivning |
|---|---|---|
invalid_request_error | 400, 413, 415, 422 | Själva begäran är fel: ett fält, kroppen, modell-id:t eller en input som modellen inte tar. Ändra begäran innan du skickar den igen. |
authentication_error | 401 | API-nyckeln saknas, är okänd eller är återkallad. |
not_found_error | 404 | Sökvägen finns inte. |
rate_limit_error | 429 | Balansen täcker inte begäran, flood protection stoppade den, eller modellen är upptagen. Meddelandet anger vilket. |
api_error | 500, 502, 503, 504 | Begäran var korrekt och felet ligger hos oss. Skicka den igen. |
server_error | 500 | Begäran var korrekt och felet ligger hos oss. Skicka den igen. |
Statuskoder
| Status | Typ | Meddelande | När |
|---|---|---|---|
400 | invalid_request_error | Failed to parse the request body as JSON: … | Kroppen är inte giltig JSON. |
400 | invalid_request_error | unknown model: <id> | model är inte ett publicerat id. På /v1/responses även när model saknas. |
400 | invalid_request_error | No user message provided | Shannon-nivåer: begäran innehåller ingen användartext. |
400 | invalid_request_error | <id> does not accept image input | En bild skickades till en hostad open-weight-modell utan bildinput. |
400 | invalid_request_error | audio and video input are not supported by any hosted model | En ljud- eller videodel skickades till en hostad open-weight-modell. |
400 | invalid_request_error | <id> does not accept response_format | Strukturerad utdata begärdes av en hostad open-weight-modell som saknar det. |
400 | invalid_request_error | <id> does not accept response_format json_schema; use json_object | Ett JSON-schema skickades till en hostad open-weight-modell som endast tar json_object. |
400 | invalid_request_error | unknown reasoning effort '<value>'; expected off, low, medium or high | Resonemangsansträngningen är inte ett av de listade värdena. Hostade open-weight-modeller. |
400 | invalid_request_error | count_tokens is available for the hosted open models; unknown model: <id> | Tokenräkning begärdes för en modell utanför de hostade open-weight-modellerna. |
401 | authentication_error | Missing authentication | Ingen API-nyckel skickades. |
401 | authentication_error | Invalid API key | Nyckeln är okänd, ersattes av en nyare eller återkallades. |
404 | not_found_error | Not Found | Sökvägen finns inte, till exempel /v1/embeddings. |
405 | api_error | Method Not Allowed | Sökvägen finns men inte med denna HTTP-metod. |
413 | invalid_request_error | Failed to buffer the request body: … | Begäranskroppen är större än 32 MiB. |
415 | invalid_request_error | Expected request with `Content-Type: application/json` | Headern Content-Type saknas eller är inte application/json. |
422 | invalid_request_error | Failed to deserialize the JSON body into the target type: … | Ett obligatoriskt fält saknas, till exempel messages, eller ett fält har fel JSON-typ. |
429 | rate_limit_error | Quota exceeded. Upgrade your plan at shannon-ai.com/plan | Begärans outputgräns är större än vad som återstår av din balans. |
429 | rate_limit_error | Too many requests. Retry in <n>s. | Flood protection: fler än 120 begäranden på en minut på ditt konto. <n> är antalet sekunder tills minuten är slut. |
429 | rate_limit_error | Shannon Coder call quota reached. Upgrade your plan at shannon-ai.com/plan | shannon-coder-1 på /v1/chat/completions och /v1/messages: de Shannon Coder-anrop som din plan ger för det aktuella 4-timmarsfönstret är förbrukade. |
429 | rate_limit_error | Shannon routes are temporarily busy. Please retry. | Modellen är upptagen just nu. |
500 | server_error | The model backend failed to answer. Please retry. | Modellen gav inget svar. |
500 | server_error | An internal error occurred. Please retry. | Ett internt fel medan begäran förbereddes. |
502 | api_error | The model backend failed to answer. Please retry. | Modellen gav inget svar. Shannon 3-familjen och hostade open-weight-modeller. |
503 | api_error | Could not verify your quota right now. Please retry. | Din balans kunde inte läsas just nu. |
503 | api_error | token counting is temporarily unavailable for this model | Tokenräkning är inte tillgänglig för den här modellen just nu. |
504 | api_error | upstream timed out | En hostad open-weight-modell tog längre tid än tidsgränsen för en begäran som inte streamas. |
Kontrollerna körs i den här ordningen: API-nyckel, begäranskropp, modell-id, flood protection, balans. En begäran med fel nyckel och fel kropp returnerar därför 401. En begäran som avvisas med en 4xx-status debiteras inte.
Balans och flood protection
Varje begäran betjänas lika: det finns inga hastighetsnivåer och ingen separat API-kvot. Två saker kan ändå ge svaret 429, båda med typen rate_limit_error. Meddelandet skiljer dem åt.
Balans
Din balans är dagens plankvot, som återställs kl. 00:00 UTC, och efter den din inköpta kredit. Chatten och API:et drar från samma balans.
Varje begäran reserverar först sin outputgräns: max_tokens, eller max_output_tokens på /v1/responses, 4,096 när du inte skickar någon av dem. När svaret är klart ersätts det reserverade beloppet av det som begäran förbrukade. Om beloppet inte ryms i den återstående balansen returnerar begäran Quota exceeded innan modellen startar.
Begäranden som körs samtidigt reserverar var sitt belopp. Många parallella begäranden med högt max_tokens kan därför förbruka balansen för ett ögonblick, även när varje svar är kort. Ett lägre max_tokens reserverar mindre.
Flood protection
Flood protection tillåter 120 begäranden per minut och konto. Det räknar kontot, inte nyckeln, över /v1/chat/completions, /v1/responses och /v1/messages tillsammans. Minuten börjar med din första begäran.
Begäran nummer 121 inom den minuten returnerar Too many requests. Retry in <n>s. och kostar ingenting. Avvisade begäranden räknas också, så en klient som skickar igen utan att vänta förblir avvisad tills minuten är slut. Vänta de <n> sekunder som anges i meddelandet.
Begäranden som skickas parallellt avvisas inte för att de är parallella. De väntar i kö och besvaras i tur och ordning.
GET /v1/models och endpointsen för tokenräkning räknas inte.
Mer om gränser och balans, och var du ser din egen balans och användning: Gränser och balans Nycklar och användning
Vad som ska försökas igen
Skicka en begäran igen bara när samma begäran kan lyckas. OpenAI- och Anthropic-SDK:erna försöker redan själva igen två gånger vid svar med 429 och 5xx; ställ in max_retries (maxRetries i JavaScript) för att ändra det.
| Fel | Skicka igen? | Hur |
|---|---|---|
400, 404, 405, 413, 415, 422 | Nej. Rätta begäran först. | Meddelandet anger vilket fält, vilken modell eller vilken input som är fel. |
401 | Nej. Använd en giltig nyckel. | Skapa eller ersätt nyckeln på sidan Nycklar och användning. |
429 Too many requests | Ja, efter väntetiden. | Vänta det antal sekunder som anges i meddelandet och skicka sedan samma begäran. |
429 Quota exceeded | Inte som den är. | Sänk max_tokens, vänta på den dagliga återställningen kl. 00:00 UTC, eller fyll på kredit. |
429 Shannon Coder call quota reached | Ja, i nästa fönster. | Fönstren börjar var 4:e timme från 00:00 UTC. En annan modell svarar direkt. |
429 … temporarily busy | Ja. | Vänta några sekunder, därefter längre vid varje nytt försök. |
500, 502, 503 | Ja. | Vänta 1 sekund, sedan 2, 4 och 8. Sluta efter några försök och rapportera begärans-id:t. |
504 | Ja. | Skicka den med stream satt till true: tidsgränsen gäller svar som inte streamas. |
En retry-loop som följer den här tabellen:
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) import OpenAI from "openai";
// maxRetries: 0 — this loop does the retrying, the SDK does not add its own.
const client = new OpenAI({ apiKey: "YOUR_API_KEY", baseURL: "https://api.shannon-ai.com/v1", maxRetries: 0 });
const sleep = (seconds) => new Promise((resolve) => setTimeout(resolve, seconds * 1000));
async function createWithRetry(request, attempts = 5) {
for (let attempt = 0; attempt < attempts; attempt++) {
try {
return await client.chat.completions.create(request);
} catch (error) {
const text = String(error.message);
const flood = text.match(/Retry in (\d+)s/);
if (error.status === 429 && flood) {
await sleep(Number(flood[1])); // flood protection: wait out the minute
} else if (error.status === 429 && text.includes("temporarily busy")) {
await sleep(2 ** attempt);
} else if (error.status >= 500 || error instanceof OpenAI.APIConnectionError) {
await sleep(2 ** attempt); // 1, 2, 4, 8 seconds
} else {
throw error; // wrong request, wrong key or balance
}
}
}
throw new Error("the request failed after all attempts");
}
const response = await createWithRetry({
model: "shannon-3",
messages: [{ role: "user", content: "Hello" }],
});
console.log(response.choices[0].message.content); Fel inuti en ström
En ström har status 200 från sin första byte. Ett fel därefter kommer som en händelse inuti strömmen: en chunk med en error-medlem på /v1/chat/completions, en error-händelse på /v1/messages, en response.failed- eller error-händelse på /v1/responses. Strömmens avslutande händelser följer ändå. Behandla ett sådant svar som misslyckat och skicka begäran igen, som vid en 5xx-status.
En konversation som är längre än modellens kontextfönster rapporteras på det här sättet, med typen invalid_request_error och koden context_length_exceeded. Korta ner konversationen innan du skickar igen.
De exakta ramarna beskrivs under streaming. Streaming
Begärans-id:n
Varje svar, även fel, har en x-request-id-header. Den är det värde du skickade i din egen x-request-id-header, eller 12 hexadecimala tecken när du inte skickade något. Logga den och ange den när du ber om hjälp med en begäran.