Vai al contenuto
Gestione errori

Gestione errori

Una richiesta che fallisce restituisce un codice di stato HTTP e un corpo JSON con un tipo di errore e un messaggio. Questa pagina elenca ogni stato, mostra il corpo dell'errore di ogni formato API e indica quali errori vale la pena reinviare.

Gli SDK sollevano un oggetto di errore che porta il codice di stato e i campi del corpo. Questa richiesta indica un modello che non esiste:

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

Restituisce lo stato 400 e questo corpo:

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

Corpo dell'errore

Ci sono due corpi. /v1/messages risponde nel formato Anthropic; ogni altro endpoint risponde nel formato OpenAI. In entrambi, i dettagli sono in error.type e error.message, quindi un solo lettore serve tutti gli endpoint.

401 Formato OpenAI
{
  "error": {
    "type": "authentication_error",
    "message": "Invalid API key",
    "code": "invalid_api_key",
    "param": null
  }
}
401 Formato Anthropic
{
  "type": "error",
  "error": {
    "type": "authentication_error",
    "message": "Invalid API key"
  }
}
Campo Tipo Descrizione
error.type string Il tipo di errore. Vedi Tipi di errore più sotto.
error.message string Una frase per una persona. I testi nelle tabelle qui sotto sono stabili tranne che nelle parti variabili, indicate come <id>, <n> o ….
error.code string | null Presente in alcuni errori del formato OpenAI: invalid_api_key con 401, request_too_large con 413, context_length_exceeded quando una conversazione è troppo lunga, altrimenti null o assente. Decidi prima in base allo stato e a error.type e tratta code come un extra.
error.param null Presente negli stessi errori di code. Sempre null.
type string Solo formato Anthropic. Sempre error.

Tipi di errore

Tipo Stati Descrizione
invalid_request_error 400, 413, 415, 422 La richiesta stessa è sbagliata: un campo, il corpo, l'id del modello o un input che il modello non accetta. Modifica la richiesta prima di inviarla di nuovo.
authentication_error 401 La chiave API manca, è sconosciuta o revocata.
not_found_error 404 Il percorso non esiste.
rate_limit_error 429 Il saldo non copre la richiesta, la flood protection l'ha fermata, oppure il modello è occupato. Il messaggio indica quale.
api_error 500, 502, 503, 504 La richiesta era corretta e il guasto è dalla nostra parte. Inviala di nuovo.
server_error 500 La richiesta era corretta e il guasto è dalla nostra parte. Inviala di nuovo.

Codici di stato

Stato Tipo Messaggio Quando
400 invalid_request_error Failed to parse the request body as JSON: … Il corpo non è JSON valido.
400 invalid_request_error unknown model: <id> model non è un id pubblicato. Su /v1/responses anche quando model manca.
400 invalid_request_error No user message provided Livelli Shannon: la richiesta non contiene testo dell'utente.
400 invalid_request_error <id> does not accept image input È stata inviata un'immagine a un modello open-weight ospitato senza input di immagini.
400 invalid_request_error audio and video input are not supported by any hosted model È stata inviata una parte audio o video a un modello open-weight ospitato.
400 invalid_request_error <id> does not accept response_format È stato richiesto l'output strutturato a un modello open-weight ospitato che non lo prevede.
400 invalid_request_error <id> does not accept response_format json_schema; use json_object È stato inviato uno schema JSON a un modello open-weight ospitato che accetta solo json_object.
400 invalid_request_error unknown reasoning effort '<value>'; expected off, low, medium or high Lo sforzo di ragionamento non è uno dei valori elencati. Modelli open-weight ospitati.
400 invalid_request_error count_tokens is available for the hosted open models; unknown model: <id> È stato richiesto il conteggio dei token per un modello che non è tra i modelli open-weight ospitati.
401 authentication_error Missing authentication Non è stata inviata alcuna chiave API.
401 authentication_error Invalid API key La chiave è sconosciuta, è stata sostituita da una più recente oppure è stata revocata.
404 not_found_error Not Found Il percorso non esiste, per esempio /v1/embeddings.
405 api_error Method Not Allowed Il percorso esiste ma non con questo metodo HTTP.
413 invalid_request_error Failed to buffer the request body: … Il corpo della richiesta è più grande di 32 MiB.
415 invalid_request_error Expected request with `Content-Type: application/json` L'header Content-Type manca oppure non è application/json.
422 invalid_request_error Failed to deserialize the JSON body into the target type: … Manca un campo obbligatorio, come messages, oppure un campo ha il tipo JSON sbagliato.
429 rate_limit_error Quota exceeded. Upgrade your plan at shannon-ai.com/plan Il limite di output della richiesta è maggiore di ciò che resta del tuo saldo.
429 rate_limit_error Too many requests. Retry in <n>s. Flood protection: più di 120 richieste in un minuto sul tuo account. <n> è il numero di secondi fino alla fine del minuto.
429 rate_limit_error Shannon Coder call quota reached. Upgrade your plan at shannon-ai.com/plan shannon-coder-1 su /v1/chat/completions e /v1/messages: le chiamate Shannon Coder del tuo piano per la finestra di 4 ore in corso sono esaurite.
429 rate_limit_error Shannon routes are temporarily busy. Please retry. Il modello è occupato in questo momento.
500 server_error The model backend failed to answer. Please retry. Il modello non ha prodotto una risposta.
500 server_error An internal error occurred. Please retry. Un guasto interno durante la preparazione della richiesta.
502 api_error The model backend failed to answer. Please retry. Il modello non ha prodotto una risposta. Famiglia Shannon 3 e modelli open-weight ospitati.
503 api_error Could not verify your quota right now. Please retry. Non è stato possibile leggere il tuo saldo in questo momento.
503 api_error token counting is temporarily unavailable for this model Il conteggio dei token non è disponibile per questo modello in questo momento.
504 api_error upstream timed out Un modello open-weight ospitato ha impiegato più del limite di tempo di una richiesta senza streaming.

I controlli vengono eseguiti in quest'ordine: chiave API, corpo della richiesta, id del modello, flood protection, saldo. Una richiesta con una chiave sbagliata e un corpo sbagliato restituisce quindi 401. Una richiesta rifiutata con uno stato 4xx non viene addebitata.

Saldo e flood protection

Ogni richiesta è servita allo stesso modo: non ci sono fasce di frequenza né una quota API separata. Due cose possono comunque rispondere 429, entrambe con il tipo rate_limit_error. Il messaggio le distingue.

Saldo

Il tuo saldo è la quota del piano di oggi, che si azzera alle 00:00 UTC, e dopo di essa il tuo credito acquistato. Chat e API attingono allo stesso saldo.

Ogni richiesta mette prima da parte il proprio limite di output: max_tokens, o max_output_tokens su /v1/responses, 4,096 se non ne invii nessuno. Quando la risposta è completa, la quantità messa da parte viene sostituita da ciò che la richiesta ha usato. Se la quantità non rientra nel saldo rimasto, la richiesta restituisce Quota exceeded prima che il modello inizi.

Le richieste eseguite nello stesso momento mettono ciascuna da parte la propria quantità. Molte richieste parallele con un max_tokens alto possono quindi esaurire il saldo per un momento, anche se ogni risposta è breve. Un max_tokens più basso mette da parte meno.

Flood protection

La flood protection consente 120 richieste al minuto per account. Conta l'account, non la chiave, su /v1/chat/completions, /v1/responses e /v1/messages insieme. Il minuto inizia con la tua prima richiesta.

La richiesta numero 121 all'interno di quel minuto restituisce Too many requests. Retry in <n>s. e non costa nulla. Contano anche le richieste rifiutate, quindi un client che reinvia senza attendere resta rifiutato fino al termine del minuto. Attendi i <n> secondi indicati nel messaggio.

Le richieste inviate in parallelo non vengono rifiutate perché parallele. Attendono in coda e ricevono risposta a turno.

GET /v1/models e gli endpoint di conteggio dei token non vengono conteggiati.

Altro su limiti e saldo, e dove vedere il tuo saldo e il tuo utilizzo: Limiti e saldo Chiavi e utilizzo

Cosa riprovare

Reinvia una richiesta solo quando la stessa richiesta può riuscire. Gli SDK di OpenAI e Anthropic riprovano già da soli due volte le risposte 429 e 5xx; imposta max_retries (maxRetries in JavaScript) per cambiarlo.

Errore Reinviare? Come
400, 404, 405, 413, 415, 422 No. Correggi prima la richiesta. Il messaggio indica il campo, il modello o l'input che è sbagliato.
401 No. Usa una chiave valida. Crea o sostituisci la chiave nella pagina Chiavi e utilizzo.
429 Too many requests Sì, dopo l'attesa. Attendi il numero di secondi indicato nel messaggio, poi invia la stessa richiesta.
429 Quota exceeded Non così com'è. Abbassa max_tokens, attendi il reset giornaliero alle 00:00 UTC, oppure aggiungi credito.
429 Shannon Coder call quota reached Sì, nella finestra successiva. Le finestre iniziano ogni 4 ore a partire dalle 00:00 UTC. Un altro modello risponde subito.
429 … temporarily busy Sì. Attendi qualche secondo, poi di più a ogni ulteriore tentativo.
500, 502, 503 Sì. Attendi 1 secondo, poi 2, 4 e 8. Fermati dopo alcuni tentativi e segnala l'id della richiesta.
504 Sì. Inviala con stream impostato su true: il limite di tempo si applica alle risposte senza streaming.

Un ciclo di retry che segue questa tabella:

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)

Errori all'interno di uno stream

Uno stream ha stato 200 fin dal primo byte. Un errore successivo arriva come evento all'interno dello stream: un chunk con un membro error su /v1/chat/completions, un evento error su /v1/messages, un evento response.failed o error su /v1/responses. Gli eventi di chiusura dello stream seguono comunque. Considera una risposta del genere come fallita e invia di nuovo la richiesta, come per uno stato 5xx.

Una conversazione più lunga della finestra di contesto del modello viene segnalata così, con il tipo invalid_request_error e il codice context_length_exceeded. Accorcia la conversazione prima di inviarla di nuovo.

I frame esatti sono descritti nella pagina sullo streaming. Streaming

Id delle richieste

Ogni risposta, errori compresi, ha un header x-request-id. È il valore che hai inviato nel tuo header x-request-id, oppure 12 caratteri esadecimali se non ne hai inviato nessuno. Registralo nei log e citalo quando chiedi aiuto per una richiesta.