Salta al contingut
Gestió d’errors

Gestió d’errors

Una sol·licitud que falla retorna un codi d'estat HTTP i un cos JSON amb un tipus d'error i un missatge. Aquesta pàgina llista tots els estats, mostra el cos d'error de cada format d'API i indica quins errors val la pena tornar a enviar.

Els SDK llancen un objecte d'error que porta el codi d'estat i els camps del cos. Aquesta sol·licitud indica un model que no existeix:

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

Retorna l'estat 400 i aquest cos:

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

Cos de l'error

Hi ha dos cossos. /v1/messages respon en el format Anthropic; tots els altres endpoints responen en el format OpenAI. En tots dos, els detalls són a error.type i error.message, de manera que un sol lector serveix per a tots els endpoints.

401 Format OpenAI
{
  "error": {
    "type": "authentication_error",
    "message": "Invalid API key",
    "code": "invalid_api_key",
    "param": null
  }
}
401 Format Anthropic
{
  "type": "error",
  "error": {
    "type": "authentication_error",
    "message": "Invalid API key"
  }
}
Camp Tipus Descripció
error.type string El tipus d'error. Vegeu Tipus d'error més avall.
error.message string Una frase per a una persona. Els textos de les taules següents són estables llevat de les parts variables, mostrades com a <id>, <n> o ….
error.code string | null Present en alguns errors del format OpenAI: invalid_api_key amb 401, request_too_large amb 413, context_length_exceeded quan una conversa és massa llarga, i en cas contrari null o absent. Decideix primer segons l'estat i error.type i tracta code com a extra.
error.param null Present als mateixos errors que code. Sempre null.
type string Només al format Anthropic. Sempre error.

Tipus d'error

Tipus Estats Descripció
invalid_request_error 400, 413, 415, 422 La sol·licitud en si és incorrecta: un camp, el cos, l'id del model o una entrada que el model no accepta. Canvia la sol·licitud abans de tornar a enviar-la.
authentication_error 401 La clau API falta, és desconeguda o està revocada.
not_found_error 404 El camí no existeix.
rate_limit_error 429 El saldo no cobreix la sol·licitud, la protecció contra inundació l'ha aturada, o el model està ocupat. El missatge indica quina és la causa.
api_error 500, 502, 503, 504 La sol·licitud era correcta i l'error és per part nostra. Torna a enviar-la.
server_error 500 La sol·licitud era correcta i l'error és per part nostra. Torna a enviar-la.

Codis d'estat

Estat Tipus Missatge Quan
400 invalid_request_error Failed to parse the request body as JSON: … El cos no és JSON vàlid.
400 invalid_request_error unknown model: <id> model no és un id publicat. A /v1/responses també quan falta model.
400 invalid_request_error No user message provided Nivells Shannon: la sol·licitud no conté cap text d'usuari.
400 invalid_request_error <id> does not accept image input S'ha enviat una imatge a un model open-weight hostejat sense entrada d'imatge.
400 invalid_request_error audio and video input are not supported by any hosted model S'ha enviat una part d'àudio o de vídeo a un model open-weight hostejat.
400 invalid_request_error <id> does not accept response_format S'ha demanat sortida estructurada a un model open-weight hostejat que no en té.
400 invalid_request_error <id> does not accept response_format json_schema; use json_object S'ha enviat un esquema JSON a un model open-weight hostejat que només accepta json_object.
400 invalid_request_error unknown reasoning effort '<value>'; expected off, low, medium or high L'esforç de raonament no és cap dels valors llistats. Models open-weight hostejats.
400 invalid_request_error count_tokens is available for the hosted open models; unknown model: <id> S'ha demanat el recompte de tokens per a un model fora dels models open-weight hostejats.
401 authentication_error Missing authentication No s'ha enviat cap clau API.
401 authentication_error Invalid API key La clau és desconeguda, s'ha substituït per una de més nova o s'ha revocat.
404 not_found_error Not Found El camí no existeix, per exemple /v1/embeddings.
405 api_error Method Not Allowed El camí existeix però no amb aquest mètode HTTP.
413 invalid_request_error Failed to buffer the request body: … El cos de la sol·licitud és més gran que 32 MiB.
415 invalid_request_error Expected request with `Content-Type: application/json` La capçalera Content-Type falta o no és application/json.
422 invalid_request_error Failed to deserialize the JSON body into the target type: … Falta un camp obligatori, com messages, o un camp té un tipus JSON incorrecte.
429 rate_limit_error Quota exceeded. Upgrade your plan at shannon-ai.com/plan El límit de sortida de la sol·licitud és més gran que el que queda del teu saldo.
429 rate_limit_error Too many requests. Retry in <n>s. Protecció contra inundació: més de 120 sol·licituds en un minut al teu compte. <n> és el nombre de segons fins que acaba el minut.
429 rate_limit_error Shannon Coder call quota reached. Upgrade your plan at shannon-ai.com/plan shannon-coder-1 a /v1/chat/completions i /v1/messages: les crides de Shannon Coder del teu pla per a la finestra actual de 4 hores s'han esgotat.
429 rate_limit_error Shannon routes are temporarily busy. Please retry. El model està ocupat en aquest moment.
500 server_error The model backend failed to answer. Please retry. El model no ha produït cap resposta.
500 server_error An internal error occurred. Please retry. Un error intern mentre es preparava la sol·licitud.
502 api_error The model backend failed to answer. Please retry. El model no ha produït cap resposta. Família Shannon 3 i models open-weight hostejats.
503 api_error Could not verify your quota right now. Please retry. El teu saldo no s'ha pogut llegir en aquest moment.
503 api_error token counting is temporarily unavailable for this model El recompte de tokens no està disponible per a aquest model en aquest moment.
504 api_error upstream timed out Un model open-weight hostejat ha trigat més que el límit de temps d'una sol·licitud sense stream.

Les comprovacions s'executen en aquest ordre: clau API, cos de la sol·licitud, id del model, protecció contra inundació, saldo. Una sol·licitud amb una clau incorrecta i un cos incorrecte retorna, doncs, 401. Una sol·licitud rebutjada amb un estat 4xx no es cobra.

Saldo i protecció contra inundació

Cada sol·licitud es serveix per igual: no hi ha nivells de límit de ritme ni una quota d'API separada. Tot i això, dues coses poden respondre 429, totes dues amb el tipus rate_limit_error. El missatge les distingeix.

Saldo

El teu saldo és la quota del pla d'avui, que es restableix a les 00:00 UTC, i després el teu crèdit comprat. El xat i l'API fan servir el mateix saldo.

Cada sol·licitud reserva primer el seu límit de sortida: max_tokens, o max_output_tokens a /v1/responses, 4,096 quan no envies cap dels dos. Quan la resposta és completa, la quantitat reservada se substitueix pel que la sol·licitud ha fet servir. Si la quantitat no cap en el saldo que queda, la sol·licitud retorna Quota exceeded abans que el model comenci.

Les sol·licituds que s'executen alhora reserven cadascuna la seva pròpia quantitat. Moltes sol·licituds en paral·lel amb un max_tokens alt poden, doncs, esgotar el saldo un moment, encara que cada resposta sigui curta. Un max_tokens més baix en reserva menys.

Protecció contra inundació

La protecció contra inundació permet 120 sol·licituds per minut per compte. Compta el compte, no la clau, sumant /v1/chat/completions, /v1/responses i /v1/messages. El minut comença amb la teva primera sol·licitud.

La sol·licitud número 121 dins d'aquest minut retorna Too many requests. Retry in <n>s. i no costa res. Les sol·licituds rebutjades també compten, de manera que un client que torna a enviar sense esperar continua rebutjat fins que s'acaba el minut. Espera els <n> segons del missatge.

Les sol·licituds enviades en paral·lel no es rebutgen pel fet de ser paral·leles. Esperen en cua i es responen per torn.

GET /v1/models i els endpoints de recompte de tokens no es compten.

Més sobre límits i saldo, i on veure el teu propi saldo i ús: Límits i saldo Keys & usage

Què cal tornar a provar

Torna a enviar una sol·licitud només quan la mateixa sol·licitud pot tenir èxit. Els SDK d'OpenAI i d'Anthropic ja reintenten per si mateixos dues vegades les respostes 429 i 5xx; defineix max_retries (maxRetries en JavaScript) per canviar-ho.

Error Tornar a enviar? Com
400, 404, 405, 413, 415, 422 No. Corregeix primer la sol·licitud. El missatge indica el camp, el model o l'entrada que és incorrecte.
401 No. Fes servir una clau vàlida. Crea o substitueix la clau a la pàgina Keys & usage.
429 Too many requests Sí, després de l'espera. Espera el nombre de segons del missatge i torna a enviar la mateixa sol·licitud.
429 Quota exceeded No tal com és. Baixa max_tokens, espera el restabliment diari a les 00:00 UTC o afegeix crèdit.
429 Shannon Coder call quota reached Sí, a la finestra següent. Les finestres comencen cada 4 hores des de les 00:00 UTC. Un altre model respon a l'instant.
429 … temporarily busy Sí. Espera uns quants segons, i més a cada intent següent.
500, 502, 503 Sí. Espera 1 segon, després 2, 4 i 8. Atura't després d'uns quants intents i informa de l'id de la sol·licitud.
504 Sí. Envia-la amb stream definit a true: el límit de temps s'aplica a les respostes sense stream.

Un bucle de reintents que segueix aquesta taula:

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)

Errors dins d'un stream

Un stream té l'estat 200 des del primer byte. Un error posterior arriba com a esdeveniment dins del stream: un fragment amb un membre error a /v1/chat/completions, un esdeveniment error a /v1/messages, un esdeveniment response.failed o error a /v1/responses. Els esdeveniments de tancament del stream continuen arribant. Considera que aquesta resposta ha fallat i torna a enviar la sol·licitud, com amb un estat 5xx.

Una conversa més llarga que la finestra de context del model s'informa d'aquesta manera, amb el tipus invalid_request_error i el codi context_length_exceeded. Escurça la conversa abans de tornar a enviar-la.

Els fragments exactes es descriuen amb el streaming. Streaming

Ids de sol·licitud

Cada resposta, errors inclosos, té una capçalera x-request-id. És el valor que has enviat a la teva pròpia capçalera x-request-id, o 12 caràcters hexadecimals si no n'has enviat cap. Registra'l i cita'l quan demanis ajuda amb una sol·licitud.