Fejlhåndtering
En anmodning, der fejler, returnerer en HTTP-statuskode og en JSON-body med en fejltype og en besked. Denne side opregner hver status, viser fejlindholdet i hvert API-format og siger, hvilke fejl det kan betale sig at sende igen.
SDK'erne rejser et fejlobjekt, der indeholder statuskoden og body'ens felter. Denne anmodning angiver en model, der ikke findes:
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 returnerer status 400 og denne body:
{
"error": {
"type": "invalid_request_error",
"message": "unknown model: no-such-model"
}
} Fejlindhold
Der er to body-former. /v1/messages svarer i Anthropic-formatet; alle andre endpoints svarer i OpenAI-formatet. I begge står detaljerne i error.type og error.message, så én læser kan bruges til alle 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"
}
} | Felt | Type | Beskrivelse |
|---|---|---|
error.type | string | Typen af fejl. Se Fejltyper nedenfor. |
error.message | string | En sætning til et menneske. Teksterne i tabellerne nedenfor er stabile bortset fra deres variable dele, vist som <id>, <n> eller …. |
error.code | string | null | Findes på nogle fejl i OpenAI-formatet: invalid_api_key med 401, request_too_large med 413, context_length_exceeded, når en samtale er for lang, ellers null eller fraværende. Afgør det ud fra status og error.type først, og behandl code som et ekstra. |
error.param | null | Findes på de samme fejl som code. Altid null. |
type | string | Kun Anthropic-format. Altid error. |
Fejltyper
| Type | Statusser | Beskrivelse |
|---|---|---|
invalid_request_error | 400, 413, 415, 422 | Selve anmodningen er forkert: et felt, body'en, model-id'et eller et input, som modellen ikke tager. Ret anmodningen, før du sender den igen. |
authentication_error | 401 | API-nøglen mangler, er ukendt eller er tilbagekaldt. |
not_found_error | 404 | Stien findes ikke. |
rate_limit_error | 429 | Saldoen dækker ikke anmodningen, flood protection stoppede den, eller modellen er optaget. Beskeden siger hvilket. |
api_error | 500, 502, 503, 504 | Anmodningen var i orden, og fejlen ligger hos os. Send den igen. |
server_error | 500 | Anmodningen var i orden, og fejlen ligger hos os. Send den igen. |
Statuskoder
| Status | Type | Besked | Hvornår |
|---|---|---|---|
400 | invalid_request_error | Failed to parse the request body as JSON: … | Body'en er ikke gyldig JSON. |
400 | invalid_request_error | unknown model: <id> | model er ikke et offentliggjort id. På /v1/responses også når model mangler. |
400 | invalid_request_error | No user message provided | Shannon-niveauer: anmodningen indeholder ingen brugertekst. |
400 | invalid_request_error | <id> does not accept image input | Et billede blev sendt til en hostet open-weight-model uden billedinput. |
400 | invalid_request_error | audio and video input are not supported by any hosted model | En lyd- eller videodel blev sendt til en hostet open-weight-model. |
400 | invalid_request_error | <id> does not accept response_format | Struktureret output blev bedt om fra en hostet open-weight-model uden det. |
400 | invalid_request_error | <id> does not accept response_format json_schema; use json_object | Et JSON-skema blev sendt til en hostet open-weight-model, der kun tager json_object. |
400 | invalid_request_error | unknown reasoning effort '<value>'; expected off, low, medium or high | Reasoning effort er ikke en af de opførte værdier. Hostede open-weight-modeller. |
400 | invalid_request_error | count_tokens is available for the hosted open models; unknown model: <id> | Tokentælling blev bedt om for en model uden for de hostede open-weight-modeller. |
401 | authentication_error | Missing authentication | Der blev ikke sendt nogen API-nøgle. |
401 | authentication_error | Invalid API key | Nøglen er ukendt, blev erstattet af en nyere eller blev tilbagekaldt. |
404 | not_found_error | Not Found | Stien findes ikke, f.eks. /v1/embeddings. |
405 | api_error | Method Not Allowed | Stien findes, men ikke med denne HTTP-metode. |
413 | invalid_request_error | Failed to buffer the request body: … | Anmodningens body er større end 32 MiB. |
415 | invalid_request_error | Expected request with `Content-Type: application/json` | Headeren Content-Type mangler eller er ikke application/json. |
422 | invalid_request_error | Failed to deserialize the JSON body into the target type: … | Et påkrævet felt mangler, f.eks. messages, eller et felt har den forkerte JSON-type. |
429 | rate_limit_error | Quota exceeded. Upgrade your plan at shannon-ai.com/plan | Anmodningens outputgrænse er større end det, der er tilbage af din saldo. |
429 | rate_limit_error | Too many requests. Retry in <n>s. | Flood protection: mere end 120 anmodninger på ét minut på din konto. <n> er antallet af sekunder, til minuttet er omme. |
429 | rate_limit_error | Shannon Coder call quota reached. Upgrade your plan at shannon-ai.com/plan | shannon-coder-1 på /v1/chat/completions og /v1/messages: din plans Shannon Coder-kald for det aktuelle 4-timers vindue er brugt. |
429 | rate_limit_error | Shannon routes are temporarily busy. Please retry. | Modellen er optaget i øjeblikket. |
500 | server_error | The model backend failed to answer. Please retry. | Modellen gav ikke noget svar. |
500 | server_error | An internal error occurred. Please retry. | En intern fejl, mens anmodningen blev forberedt. |
502 | api_error | The model backend failed to answer. Please retry. | Modellen gav ikke noget svar. Shannon 3-familien og hostede open-weight-modeller. |
503 | api_error | Could not verify your quota right now. Please retry. | Din saldo kunne ikke læses i øjeblikket. |
503 | api_error | token counting is temporarily unavailable for this model | Tokentælling er ikke tilgængelig for denne model i øjeblikket. |
504 | api_error | upstream timed out | En hostet open-weight-model brugte længere tid end tidsgrænsen for en anmodning, der ikke streames. |
Kontrollerne køres i denne rækkefølge: API-nøgle, anmodningens body, model-id, flood protection, saldo. En anmodning med en forkert nøgle og en forkert body returnerer derfor 401. En anmodning, der afvises med en 4xx-status, afregnes ikke.
Saldo og flood protection
Hver anmodning betjenes lige: der er ingen hastighedsniveauer og ingen separat API-kvote. To ting kan alligevel besvares med 429, begge med typen rate_limit_error. Beskeden skelner mellem dem.
Saldo
Din saldo er dagens plan-kvote, som nulstilles kl. 00:00 UTC, og derefter din købte kredit. Chat og API trækker fra den samme saldo.
Hver anmodning reserverer først sin outputgrænse: max_tokens eller max_output_tokens på /v1/responses, 4,096, når du ikke sender nogen af dem. Når svaret er færdigt, erstattes det reserverede beløb af det, anmodningen brugte. Hvis beløbet ikke kan rummes i den saldo, der er tilbage, returnerer anmodningen Quota exceeded, før modellen starter.
Anmodninger, der kører samtidig, reserverer hver deres beløb. Mange parallelle anmodninger med en høj max_tokens kan derfor opbruge saldoen et øjeblik, selv om hvert svar er kort. En lavere max_tokens reserverer mindre.
Flood protection
Flood protection tillader 120 anmodninger per minut per konto. Den tæller kontoen, ikke nøglen, på tværs af /v1/chat/completions, /v1/responses og /v1/messages tilsammen. Minuttet begynder med din første anmodning.
Anmodning nummer 121 inden for det minut returnerer Too many requests. Retry in <n>s. og koster ikke noget. Afviste anmodninger tæller også med, så en klient, der sender igen uden at vente, forbliver afvist, indtil minuttet er omme. Vent de <n> sekunder fra beskeden.
Anmodninger, der sendes parallelt, afvises ikke for at være parallelle. De venter i kø og besvares efter tur.
GET /v1/models og endpointene til tokentælling tælles ikke med.
Mere om grænser og saldo og om, hvor du ser din egen saldo og dit forbrug: Grænser og saldo Nøgler og forbrug
Hvad der kan prøves igen
Send kun en anmodning igen, når den samme anmodning kan lykkes. OpenAI- og Anthropic-SDK'erne prøver allerede 429- og 5xx-svar igen to gange på egen hånd; angiv max_retries (maxRetries i JavaScript) for at ændre det.
| Fejl | Send igen? | Hvordan |
|---|---|---|
400, 404, 405, 413, 415, 422 | Nej. Ret først anmodningen. | Beskeden nævner det felt, den model eller det input, der er forkert. |
401 | Nej. Brug en gyldig nøgle. | Opret eller udskift nøglen på siden Nøgler og forbrug. |
429 Too many requests | Ja, efter ventetiden. | Vent det antal sekunder, der står i beskeden, og send derefter den samme anmodning. |
429 Quota exceeded | Ikke som den er. | Sænk max_tokens, vent på den daglige nulstilling kl. 00:00 UTC, eller tilføj kredit. |
429 Shannon Coder call quota reached | Ja, i næste vindue. | Vinduerne starter hver 4. time fra kl. 00:00 UTC. En anden model svarer med det samme. |
429 … temporarily busy | Ja. | Vent et par sekunder, og derefter længere for hvert yderligere forsøg. |
500, 502, 503 | Ja. | Vent 1 sekund, derefter 2, 4 og 8. Stop efter nogle få forsøg, og oplys anmodnings-id'et. |
504 | Ja. | Send den med stream sat til true: tidsgrænsen gælder for svar, der ikke streames. |
En retry-løkke, der følger denne tabel:
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); Fejl inde i en stream
En stream har status 200 fra sin første byte. En fejl derefter kommer som en hændelse inde i streamen: en chunk med et error-medlem på /v1/chat/completions, en error-hændelse på /v1/messages, en response.failed- eller error-hændelse på /v1/responses. Streamens afsluttende hændelser følger stadig. Behandl et sådant svar som mislykket, og send anmodningen igen, som ved en 5xx-status.
En samtale, der er længere end modellens kontekstvindue, rapporteres på denne måde med typen invalid_request_error og koden context_length_exceeded. Forkort samtalen, før du sender den igen.
De præcise rammer beskrives sammen med streaming. Streaming
Anmodnings-id'er
Hvert svar, fejl inklusive, har en x-request-id-header. Det er den værdi, du sendte i din egen x-request-id-header, eller 12 hexadecimale tegn, hvis du ikke sendte nogen. Log den, og oplys den, når du beder om hjælp til en anmodning.