Upravljanje greškama
Zahtjev koji ne uspije vraća HTTP statusni kod i JSON tijelo s tipom greške i porukom. Ova stranica navodi svaki status, prikazuje tijelo greške svakog API formata i kaže koje je greške vrijedno ponovno poslati.
SDK-ovi podižu objekt greške koji nosi statusni kod i polja tijela. Ovaj zahtjev navodi model koji ne postoji:
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"}]
}' Vraća status 400 i ovo tijelo:
{
"error": {
"type": "invalid_request_error",
"message": "unknown model: no-such-model"
}
} Tijelo greške
Postoje dva tijela. /v1/messages odgovara u Anthropic formatu; svaki drugi endpoint odgovara u OpenAI formatu. U oba su detalji u error.type i error.message, pa jedan čitač služi svim endpointima.
{
"error": {
"type": "authentication_error",
"message": "Invalid API key",
"code": "invalid_api_key",
"param": null
}
} {
"type": "error",
"error": {
"type": "authentication_error",
"message": "Invalid API key"
}
} | Polje | Tip | Opis |
|---|---|---|
error.type | string | Vrsta greške. Pogledajte Tipovi grešaka u nastavku. |
error.message | string | Rečenica za čovjeka. Tekstovi u tablicama u nastavku stabilni su do svojih promjenjivih dijelova, prikazanih kao <id>, <n> ili …. |
error.code | string | null | Prisutno na nekim greškama OpenAI formata: invalid_api_key uz 401, request_too_large uz 413, context_length_exceeded kada je razgovor predug, inače null ili odsutno. Prvo odlučujte prema statusu i error.type, a code smatrajte dodatkom. |
error.param | null | Prisutno na istim greškama kao code. Uvijek null. |
type | string | Samo Anthropic format. Uvijek error. |
Tipovi grešaka
| Tip | Statusi | Opis |
|---|---|---|
invalid_request_error | 400, 413, 415, 422 | Sam zahtjev je pogrešan: polje, tijelo, id modela ili ulaz koji model ne prima. Promijenite zahtjev prije nego ga ponovno pošaljete. |
authentication_error | 401 | API ključ nedostaje, nepoznat je ili opozvan. |
not_found_error | 404 | Putanja ne postoji. |
rate_limit_error | 429 | Stanje ne pokriva zahtjev, zaustavio ga je flood protection ili je model zauzet. Poruka kaže što od toga. |
api_error | 500, 502, 503, 504 | Zahtjev je bio u redu, a kvar je na našoj strani. Pošaljite ga ponovno. |
server_error | 500 | Zahtjev je bio u redu, a kvar je na našoj strani. Pošaljite ga ponovno. |
Statusni kodovi
| Status | Tip | Poruka | Kada |
|---|---|---|---|
400 | invalid_request_error | Failed to parse the request body as JSON: … | Tijelo nije valjan JSON. |
400 | invalid_request_error | unknown model: <id> | model nije objavljeni id. Na /v1/responses i kada model nedostaje. |
400 | invalid_request_error | No user message provided | Shannon razine: zahtjev ne sadrži korisnički tekst. |
400 | invalid_request_error | <id> does not accept image input | Slika je poslana hostiranom open-weight modelu bez ulaza slike. |
400 | invalid_request_error | audio and video input are not supported by any hosted model | Audio ili video dio poslan je hostiranom open-weight modelu. |
400 | invalid_request_error | <id> does not accept response_format | Strukturirani izlaz zatražen je od hostiranog open-weight modela koji ga nema. |
400 | invalid_request_error | <id> does not accept response_format json_schema; use json_object | JSON shema poslana je hostiranom open-weight modelu koji prima samo json_object. |
400 | invalid_request_error | unknown reasoning effort '<value>'; expected off, low, medium or high | Razina napora rezoniranja nije jedna od navedenih vrijednosti. Hostirani open-weight modeli. |
400 | invalid_request_error | count_tokens is available for the hosted open models; unknown model: <id> | Brojanje tokena zatraženo je za model izvan hostiranih open-weight modela. |
401 | authentication_error | Missing authentication | API ključ nije poslan. |
401 | authentication_error | Invalid API key | Ključ je nepoznat, zamijenjen je novijim ili je opozvan. |
404 | not_found_error | Not Found | Putanja ne postoji, na primjer /v1/embeddings. |
405 | api_error | Method Not Allowed | Putanja postoji, ali ne s ovom HTTP metodom. |
413 | invalid_request_error | Failed to buffer the request body: … | Tijelo zahtjeva veće je od 32 MiB. |
415 | invalid_request_error | Expected request with `Content-Type: application/json` | Zaglavlje Content-Type nedostaje ili nije application/json. |
422 | invalid_request_error | Failed to deserialize the JSON body into the target type: … | Obavezno polje nedostaje, na primjer messages, ili polje ima pogrešan JSON tip. |
429 | rate_limit_error | Quota exceeded. Upgrade your plan at shannon-ai.com/plan | Ograničenje izlaza zahtjeva veće je od onoga što je preostalo na vašem stanju. |
429 | rate_limit_error | Too many requests. Retry in <n>s. | Flood protection: više od 120 zahtjeva u jednoj minuti na vašem računu. <n> je broj sekundi do kraja minute. |
429 | rate_limit_error | Shannon Coder call quota reached. Upgrade your plan at shannon-ai.com/plan | shannon-coder-1 na /v1/chat/completions i /v1/messages: Shannon Coder pozivi vašeg plana za trenutačni 4-satni prozor su iskorišteni. |
429 | rate_limit_error | Shannon routes are temporarily busy. Please retry. | Model je u ovom trenutku zauzet. |
500 | server_error | The model backend failed to answer. Please retry. | Model nije proizveo odgovor. |
500 | server_error | An internal error occurred. Please retry. | Interni kvar dok se zahtjev pripremao. |
502 | api_error | The model backend failed to answer. Please retry. | Model nije proizveo odgovor. Obitelj Shannon 3 i hostirani open-weight modeli. |
503 | api_error | Could not verify your quota right now. Please retry. | Vaše stanje u ovom trenutku nije bilo moguće pročitati. |
503 | api_error | token counting is temporarily unavailable for this model | Brojanje tokena u ovom trenutku nije dostupno za taj model. |
504 | api_error | upstream timed out | Hostirani open-weight model trajao je dulje od vremenskog ograničenja zahtjeva bez streama. |
Provjere se izvršavaju ovim redom: API ključ, tijelo zahtjeva, id modela, flood protection, stanje. Zahtjev s pogrešnim ključem i pogrešnim tijelom stoga vraća 401. Zahtjev koji se odbije statusom 4xx ne naplaćuje se.
Stanje i flood protection
Svaki zahtjev poslužuje se jednako: nema razina ograničenja brzine ni zasebne API kvote. Ipak, dvije stvari mogu odgovoriti s 429, obje s tipom rate_limit_error. Poruka ih razlikuje.
Stanje
Vaše stanje je današnji dopušteni iznos plana, koji se obnavlja u 00:00 UTC, a nakon njega vaš kupljeni kredit. Chat i API crpe iz istog stanja.
Svaki zahtjev prvo odvaja svoje ograničenje izlaza: max_tokens, odnosno max_output_tokens na /v1/responses, 4,096 kada ne pošaljete nijedno. Kada je odgovor gotov, odvojeni iznos zamjenjuje ono što je zahtjev iskoristio. Ako se iznos ne uklapa u preostalo stanje, zahtjev vraća Quota exceeded prije nego model počne.
Zahtjevi koji se izvršavaju istodobno svaki odvajaju svoj iznos. Mnogo paralelnih zahtjeva s visokim max_tokens stoga može načas iscrpiti stanje, čak i kada je svaki odgovor kratak. Niži max_tokens odvaja manje.
Flood protection
Flood protection dopušta 120 zahtjeva u minuti po računu. Broji račun, a ne ključ, preko /v1/chat/completions, /v1/responses i /v1/messages zajedno. Minuta počinje s vašim prvim zahtjevom.
Zahtjev broj 121 unutar te minute vraća Too many requests. Retry in <n>s. i ne košta ništa. Odbijeni zahtjevi se također broje, pa klijent koji ponovno šalje bez čekanja ostaje odbijen dok minuta ne istekne. Pričekajte <n> sekundi iz poruke.
Zahtjevi poslani paralelno ne odbijaju se zato što su paralelni. Čekaju u redu i dobivaju odgovor redom.
GET /v1/models i endpointi za brojanje tokena ne broje se.
Više o ograničenjima i stanju te gdje vidjeti vlastito stanje i upotrebu: Ograničenja i stanje Ključevi i upotreba
Što ponoviti
Zahtjev ponovno šaljite samo kada isti zahtjev može uspjeti. OpenAI i Anthropic SDK-ovi već sami dvaput ponavljaju odgovore 429 i 5xx; postavite max_retries (maxRetries u JavaScriptu) da to promijenite.
| Greška | Poslati ponovno? | Kako |
|---|---|---|
400, 404, 405, 413, 415, 422 | Ne. Prvo ispravite zahtjev. | Poruka navodi polje, model ili ulaz koji je pogrešan. |
401 | Ne. Koristite valjan ključ. | Izradite ili zamijenite ključ na stranici Ključevi i upotreba. |
429 Too many requests | Da, nakon čekanja. | Pričekajte broj sekundi iz poruke, zatim pošaljite isti zahtjev. |
429 Quota exceeded | Ne ovakav kakav jest. | Smanjite max_tokens, pričekajte dnevno obnavljanje u 00:00 UTC ili dodajte kredit. |
429 Shannon Coder call quota reached | Da, u sljedećem prozoru. | Prozori počinju svaka 4 sata od 00:00 UTC. Drugi model odgovara odmah. |
429 … temporarily busy | Da. | Pričekajte nekoliko sekundi, a pri svakom sljedećem pokušaju dulje. |
500, 502, 503 | Da. | Pričekajte 1 sekundu, zatim 2, 4 i 8. Zaustavite se nakon nekoliko pokušaja i prijavite id zahtjeva. |
504 | Da. | Pošaljite ga s stream postavljenim na true: vremensko ograničenje vrijedi za odgovore bez streama. |
Petlja ponavljanja koja slijedi ovu tablicu:
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); Greške unutar streama
Stream ima status 200 od prvog bajta. Kvar nakon toga stiže kao događaj unutar streama: chunk s članom error na /v1/chat/completions, događaj error na /v1/messages, događaj response.failed ili error na /v1/responses. Završni događaji streama i dalje slijede. Takav odgovor smatrajte neuspjelim i ponovno pošaljite zahtjev, kao za status 5xx.
Razgovor duži od kontekstnog prozora modela prijavljuje se na ovaj način, s tipom invalid_request_error i kodom context_length_exceeded. Skratite razgovor prije nego ga ponovno pošaljete.
Točni okviri opisani su uz streaming. Streaming
Id-ovi zahtjeva
Svaki odgovor, uključujući greške, ima zaglavlje x-request-id. To je vrijednost koju ste poslali u vlastitom zaglavlju x-request-id ili 12 heksadecimalnih znakova ako niste poslali nijednu. Zapišite je u log i navedite je kada tražite pomoć oko zahtjeva.