aisplice

Quando qualcosa va storto

Cerca un errore

#Incolla l'errore

Leggi gli errori in quest'ordine: stato HTTP, poi error.type, poi error.code. Lo stato ha sempre un significato; type ti dice chi ha rifiutato la chiamata; code è stabile solo per gli errori generati dal gateway stesso.

#Come gestire i casi

  1. 1

    Decidi in base allo stato

    402 significa ricaricare, 403 ambito della chiave, 429 attendere, 5xx riprovare. Questo livello non mente mai e non cambia mai.

  2. 2

    Controlla error.type

    xiaoxiang_error è nostro. Qualsiasi altro — openai_error, claude_error, gemini_error — è il corpo del fornitore, inoltrato invariato.

  3. 3

    Poi leggi error.code

    Decidi in base a code solo per xiaoxiang_error. I codici upstream appartengono al fornitore e possono cambiare senza preavviso.

Non tutti gli errori hanno un corpo JSON

I rifiuti per limite di frequenza e i corpi troppo grandi terminano con la sola riga di stato. Un parser che presume che response.json() riesca sempre genererà un'eccezione nel percorso di errore invece di gestirlo.
Strutture degli errori

Al tuo client arrivano cinque forme. Gestiscile tutte e cinque — le ultime tre sono quelle che le integrazioni di solito dimenticano.

Errore del gateway

Il gateway stesso ha rifiutato la chiamata — autenticazione, quota, routing, forma della richiesta.

http
{
  "error": {
    "message": "insufficient account balance, please top up to continue (request id: 20260910...)",
    "type": "xiaoxiang_error",
    "code": "insufficient_user_quota"
  }
}

Errore upstream, inoltrato così com'è

Il fornitore ha risposto con un proprio errore. Il corpo viene inoltrato invariato, quindi type e code sono quelli del fornitore.

http
{
  "error": {
    "message": "This model's maximum context length is 128000 tokens.",
    "type": "invalid_request_error",
    "code": "context_length_exceeded"
  }
}

Rifiuto da controllo preliminare

L'idempotenza e alcuni altri controlli preliminari rispondono prima che esista l'envelope del relay. Struttura piatta, code in maiuscolo.

http
{
  "code": "IDEMPOTENCY_IN_PROGRESS",
  "error": "a request with this Idempotency-Key is still processing"
}

Rifiuto di task asincrono

Ogni endpoint dei task — video, task immagine, musica, 3D — riporta gli errori in una propria struttura piatta. Qui non c'è un oggetto error annidato, quindi un parser scritto per /v1/chat/completions legge null.

http
{
  "code": "task_not_exist",
  "message": "task does not exist",
  "data": null
}

Solo stato, corpo vuoto

I rifiuti per limite di frequenza e i corpi di richiesta troppo grandi terminano con il solo stato.

http
HTTP/1.1 429 Too Many Requests
Retry-After: 20
Content-Length: 0
Header di risposta

Registra l'ID richiesta di ogni risposta, non solo degli errori. È l'identificativo con cui l'assistenza rintraccia una chiamata, e fa la differenza tra una risposta in cinque minuti e una giornata di congetture.

HeaderInviato quandoCome usarlo
X-Oneapi-Request-IdOgni risposta, di successo o di errore.Registralo accanto al tuo trace id. L'assistenza risponde ai ticket partendo da questo valore, e lo stesso id viene aggiunto ai messaggi di errore del gateway.
Retry-AfterCon 429, e con 409 mentre una Idempotency-Key è ancora in elaborazione.Attendi almeno questo numero di secondi. È l'unica indicazione di backoff che il gateway invia.
X-Idempotent-ReplayedPer una Idempotency-Key ripetuta viene riprodotta una risposta salvata.true significa che non è stato eseguito nuovo lavoro e non è stato addebitato nulla di nuovo — tratta il corpo come il risultato originale.
X-Idempotency-SealedLa risposta originale non può essere riprodotta in sicurezza (per esempio uno stream o un corpo troppo grande).Smetti di riprovare con quella chiave. Riconcilia invece tramite l'endpoint del task o i tuoi registri.
log-the-request-id.ts
const response = await fetch(url, init);
const requestId = response.headers.get("X-Oneapi-Request-Id");

if (!response.ok) {
  // Bodies are absent on 429 and 413 — never assume JSON here.
  const detail = await response.text();
  logger.error({ status: response.status, requestId, detail });
  throw new GatewayError(response.status, requestId, detail);
}

#Tabella dei codici di errore

Errori generati dal gateway stesso, sempre con type "xiaoxiang_error". Due righe condividono lo stato 429 ma significano cose opposte — leggi il code prima di applicare il backoff.

HTTPCodiceSignificatoCosa fareRiprovare?
401nessunoBearer token mancante, malformato, eliminato o disattivato. Questo livello non imposta alcun code — basati sullo stato.Controlla l'header Authorization e lo stato della chiave in Console → Chiavi API.no
401signature_requiredLa chiave ha la firma delle richieste attiva e alla richiesta mancano X-Timestamp, X-Nonce o X-Signature.Firma ogni richiesta fatta con questa chiave (Autenticazione e chiavi → Firma delle richieste), oppure disattiva la firma sulla chiave.no
401signature_expiredX-Timestamp non è in secondi Unix a 10 cifre o si discosta di oltre 5 minuti dall'ora del server. La risposta include X-Server-Timestamp.Correggi l'orologio del client in base alla differenza con X-Server-Timestamp e firma di nuovo con un nuovo nonce.sì
401signature_invalidX-Signature non corrisponde al segreto di firma della chiave, oppure X-Nonce è malformato.Firma timestamp, nonce, metodo e percorso (senza query string) uniti da a capo, con il segreto attuale preso da Console → Chiavi API.no
401signature_replayedQuesto X-Nonce è già stato usato con questa chiave negli ultimi 10 minuti.Genera un nuovo nonce casuale per ogni richiesta, inclusi i nuovi tentativi.sì
403access_deniedL'IP chiamante non è nella lista di IP consentiti della chiave.Aggiungi l'indirizzo di uscita in Console → Chiavi API, oppure rimuovi la lista consentiti per le chiavi senza IP fisso.no
403nessunoAccount sospeso, oppure la chiave non può usare questo modello o canale.Controlla prima la lista dei modelli consentiti della chiave; se non ha restrizioni, apri un ticket — è l'account stesso a essere bloccato.no
400unsupported_endpointIl modello esiste ma non serve questo percorso. Il messaggio elenca gli endpoint che serve.Sposta la chiamata su un endpoint elencato — i modelli di task immagine non rispondono su /v1/chat/completions.no
400read_request_body_failedImpossibile leggere il corpo della richiesta — upload troncato, Content-Type errato o uno stream terminato in anticipo.Invia un corpo completo con un Content-Type coerente. Reinviare la stessa richiesta difettosa fallisce allo stesso modo.no
402insufficient_user_quotaIl saldo del portafoglio non copre l'importo pre-riservato per questa chiamata.Ricarica in Console → Portafoglio, poi riprova.no
429insufficient_user_quotaÈ stato raggiunto il limite di spesa giornaliero dell'account. Stesso stato della limitazione di frequenza, significato opposto — il backoff non lo risolve.Aumenta o rimuovi il limite nelle impostazioni dell'account, oppure riprendi domani. Decidi in base al code, non al solo 429.no
429nessunoLimitazione RPM/RPD per chiave o controllo di concorrenza. Il corpo è vuoto; Retry-After indica l'attesa.Attendi Retry-After secondi, poi riprova con backoff esponenziale e jitter.sì
413read_request_body_failedIl corpo della richiesta supera la dimensione accettata. Il limite a livello di trasporto termina con un corpo vuoto.Riduci il payload — carica i file tramite /v1/media/upload-policy e invia l'URL invece del Base64.no
422invalid_requestNessun canale supporta questo intento multimediale per il modello — per esempio da immagine a video su una route solo da testo a video.Controlla gli intenti supportati nella scheda del modello e cambia modello o intento.no
503model_not_foundNome del modello sconosciuto, oppure nessun canale funzionante lo serve al momento. Nota lo stato: un modello sconosciuto restituisce 503, non 404.Verifica il nome su /v1/models, poi riprova — di solito il failover trova un canale funzionante al tentativo successivo.sì
500sensitive_words_detectedIl prompt è stato bloccato dal filtro dei contenuti prima di lasciare il gateway.Modifica il prompt. Riprovare con lo stesso testo fallisce sempre.no
500count_token_failedIl gateway non è riuscito a stimare i token per il prezzo, di solito a causa di un array di messaggi malformato.Convalida l'array messages; se è ben formato, riprova e apri un ticket con l'id della richiesta.sì
500invalid_requestImpossibile interpretare la richiesta in una forma accettata da questo endpoint. Nota lo stato — un corpo che il gateway non riesce a leggere viene segnalato come 500, non 400.Convalida il JSON rispetto al riferimento dell'endpoint prima di riprovare.no
502do_request_failedIl fornitore non era raggiungibile, oppure ha restituito un errore che il gateway non è riuscito a recuperare con il failover.Riprova con backoff — il tentativo successivo di solito finisce su un canale diverso.sì
504do_request_failedIl fornitore non ha risposto entro la scadenza del gateway.Riprova con backoff; i prompt lunghi e i fornitori sotto carico vanno più spesso in timeout.sì
499do_request_failedIl tuo client ha chiuso la connessione prima dell'arrivo della risposta — di solito è il tuo timeout HTTP che scatta a metà dello stream.Aumenta il timeout di lettura del client. Le generazioni lunghe richiedono minuti, non il valore predefinito della maggior parte delle librerie HTTP.no
Errori del controllo di idempotenza

Provengono dal controllo anti-replay che precede il relay, quindi usano la forma piatta {code, error} con code in maiuscolo invece della struttura OpenAI.

HTTPCodiceSignificatoCosa fareRiprovare?
400IDEMPOTENCY_STREAM_UNSUPPORTEDIdempotency-Key inviata su una richiesta in streaming.Rimuovi l'header per le chiamate in streaming, oppure imposta stream:false quando ti serve la protezione da replay.no
400IDEMPOTENCY_BODY_UNREADABLEImpossibile calcolare l'hash del corpo per il registro di idempotenza.Invia un normale corpo JSON o multipart — i corpi chunked che non possono essere bufferizzati vengono rifiutati.no
409IDEMPOTENCY_PAYLOAD_CONFLICTQuesta chiave è già stata usata con un corpo, un percorso o una query diversi.Genera una nuova chiave. Una chiave identifica una singola richiesta esatta, non un ciclo di tentativi.no
409IDEMPOTENCY_IN_PROGRESSLa prima richiesta con questa chiave è ancora in esecuzione.Attendi Retry-After (2s) e riprova con la stessa chiave — riceverai la risposta originale.sì
409IDEMPOTENCY_RESULT_UNREPLAYABLELa richiesta originale è terminata, ma la sua risposta è stata sigillata e non può essere riprodotta.Non reinviare alla cieca. Riconcilia prima tramite l'endpoint del task o i tuoi registri.no
503IDEMPOTENCY_UNAVAILABLEIl registro di idempotenza non è disponibile, quindi il controllo blocca la richiesta invece di rischiare un doppio addebito.Riprova con backoff — la richiesta non è stata eseguita.sì

Come funzionano le chiavi di idempotenza →

Errori dei task asincroni

Gli endpoint di video, task immagine, musica e 3D rispondono con una propria forma piatta — {code, message, data} — sia per l'invio sia per il polling e l'annullamento. Una particolarità da prevedere: interrogare un id di task sconosciuto restituisce 400, annullarlo 404.

HTTPCodiceSignificatoCosa fareRiprovare?
400task_not_existPolling o remix di un id di task che non esiste o appartiene a un altro account. Nota lo stato — interrogare un task sconosciuto restituisce 400, mentre annullarlo restituisce 404.Salva task_id al momento dell'invio ed esegui il polling esattamente con quel valore.no
400invalid_requestManca un campo obbligatorio — prompt in un remix, task_id in un recupero.Correggi il corpo o il percorso prima di riprovare.no
400task_channel_disableUn task successivo (remix, extend) è vincolato al canale del task originale, e quel canale ora è disattivato.Invia un nuovo task invece di derivarlo da quello vecchio.no
400invalid_source_taskIl task di origine è del tipo sbagliato per questa operazione — per esempio un id video passato a una continuazione 3D.Verifica che l'id di origine provenga dalla stessa famiglia di funzionalità.no
404task_not_existAnnullamento di un id di task che non esiste o non è tuo.Niente da annullare — consideralo già eliminato.no
409task_not_cancellableIl task ha già raggiunto uno stato finale, quindi non c'è nulla da annullare.Interroga ancora una volta e usa il risultato che hai già pagato.no
501task_cancel_not_supportedIl provider dietro questo task non espone un'API di annullamento. La maggior parte non lo fa — l'annullamento è l'eccezione, non la regola.Lascia che il task finisca. Progetta la UI in modo che l'annullamento sia best-effort, non una garanzia.no
502cancel_task_failedIl provider non era raggiungibile durante l'annullamento. Il task è invariato.Riprova una volta, poi lascia che finisca.sì

Ciclo di vita dei task asincroni →

Non hai ancora risolto?

Inviaci l'ID richiesta o il messaggio di errore e verificheremo.