IT ▾
Ottieni chiave API

Guida ai codici di errore API senza censura e risoluzione problemi

Gli errori non spaventano, ma non sapere se retryare o modificare il codice sì. Questa guida analizza i codici di stato: trigger, criteri e correzioni. Il corpo dell'errore è sempre JSON con code e message: leggi prima il body, non solo lo status code. Include retry con backoff esponenziale, rate limiting client e checklist.

Aggiornato il

Punti chiave

  • Solo 429 e 503 meritano retry automatici; retryare sugli altri codici spreca solo richieste.
  • 402 no_credit indica saldo esaurito o prova scaduta; 403 content_blocked indica contenuto bloccato. Non sono problemi di rete.
  • I retry devono includere backoff esponenziale con jitter casuale e un numero massimo di tentativi.
  • Ogni chiave API ha un limite di 300 richieste al minuto; per i task batch applica il rate limiting lato client.

Formato corpo errore e ordine di lettura

Tutte le risposte di errore hanno la stessa struttura:

{"error":{"code":"...","message":"..."}}

L'ordine di lettura è fisso in tre passaggi:

  1. 1. Codice di stato HTTP: definisce la categoria.
  2. error.code indica la causa; usalo nel codice per i branch;
  3. error.message è per gli umani: scrivilo nei log, non fare match di stringhe.

Definisci chiaramente la distinzione: cosa si risolve con il retry (429, 503, timeout di rete) e cosa richiede una modifica (tutto il resto). Mescolarle è la causa principale di incidenti, come retryare su 402 generando decine di richieste inutili al secondo.

Nei log fissa sempre: timestamp, codice stato, error.code, stima prompt_tokens. Così vedi subito picchi di errori. Imposta un alert: 402 notifica immediata (servizio non disponibile); 429 solo se il tasso è alto (problema di concorrenza).

Ricerca rapida codici di stato

Codice di statoerror.codeSignificatoRetry?
400—Richiesta non valida, es. prompt + max_tokens > 100kNo
401—Chiave non valida o mancanteNo
402no_creditSaldo esaurito o prova scadutaNo
403content_blockedContenuto bloccatoNo
404—Endpoint non trovatoNo
429—Rate limit raggiuntoSì, backoff
503upstream_busyServizio temporaneamente occupatoSì, dopo pochi secondi

Il simbolo “—” indica che non c'è un codice fisso da gestire; gestisci in base allo status code.

4xx: modifica la richiesta, non retryare

400 Richiesta non valida

  • Causa 1: errore JSON, spesso per virgolette non escapeate nelle stringhe scritte a mano.
  • Causa 2: prompt + max_tokens supera 100.000. Le conversazioni lunghe lo attivano facilmente.
  • Causa 3: Corpo della richiesta > 8 MB.
  • Correzione: serializza con libreria JSON; stima i token prima di inviare; se superi il limite, taglia la cronologia o riduci max_tokens; vediPratica sul contesto lungo.

401 Problemi con la chiave

  • Header mancante o manca il prefisso Bearer .
  • Hai rigenerato la chiave: quella vecchia è invalidata, ma una certa macchina la sta ancora usando.
  • La variabile d'ambiente non è stata passata al container o al task programmato.

402 no_credit

Saldo esaurito o prova 7 giorni scaduta. Vai allapagina dell'accountper ricaricare il credito prepagato e ripristinare. Monitora il saldo del tuo servizio, non aspettare che l'utente veda un errore.

403 content_blocked

Contenuto bloccato. I contenuti per adulti legali, la finzione e i temi controversi non sono rifiutati, ma il contenuto sessuale minorile è sempre bloccato. Con 403, controlla input e cronologia, non retryare cambiando la formulazione.

404 endpoint non trovato

Solo due endpoint: POST /v1/chat/completions e GET /v1/models. Errori 404 se manca /v1, ci sono slash extra, il path è sbagliato o chiami embeddings/image non supportati.

Alcuni 400 sono ingannevoli: i token crescono linearmente con le conversazioni lunghe. Di giorno i test vanno bene, ma dopo decine di round arrivano 400. Non è instabilità, è il contesto al limite. Imposta un max alla cronologia o compatta i vecchi messaggi. Stima prima di inviare.

Un trucco per il debug degli errori 401: stampa nei log le prime e le ultime quattro cifre della chiave, non il contenuto completo, e confrontale con quelle visibili nella pagina dell'account. Questo ti permette di confermare se il processo sta leggendo effettivamente la chiave che credi, soprattutto in ambienti containerizzati o di pianificazione, dove la causa più comune è la mancanza o la lettura di valori vecchi delle variabili d'ambiente.

429 e 503: le due classi da ritentare

Limite di richieste 429

300 richieste al minuto per chiave. Batch, chiavi condivise o tempeste di retry le attivano. Soluzione: prima limiti di richiesta lato client, poi retry con backoff sui 429.

503 upstream_busy

Il servizio è temporaneamente occupato; riprova dopo qualche secondo. Non inviare richieste consecutive immediatamente e non ritentare dieci volte in un secondo, perché peggioreresti la situazione.

Timeout di rete

La generazione di testo lungo richiede tempo: imposta un timeout di 120 s. Attenzione ai retry: la richiesta potrebbe essere già stata eseguita su una certa macchina, consumando credito due volte. Limita i retry per le richieste di generazione e usa lo streaming.

import os
import random
import time
import requests

URL = "https://api.wushenchaapi.com/v1/chat/completions"
HEADERS = {
    "Authorization": "Bearer " + os.environ["API_KEY"],
    "Content-Type": "application/json",
}
RETRYABLE = {429, 503}          # 只重试这两类
FATAL = {400, 401, 402, 403, 404}

class ApiError(Exception):
    def __init__(self, status, code, message):
        super().__init__(f"{status} {code}: {message}")
        self.status, self.code = status, code

def call(payload, max_retries=5, base=1.0, cap=30.0):
    for attempt in range(max_retries + 1):
        try:
            r = requests.post(URL, headers=HEADERS, json=payload, timeout=120)
        except (requests.ConnectionError, requests.Timeout):
            r = None                      # 网络层失败,按可重试处理
        if r is not None and r.ok:
            return r.json()
        if r is not None:
            try:
                err = r.json().get("error", {})
            except ValueError:
                err = {}
            if r.status_code in FATAL or r.status_code not in RETRYABLE:
                raise ApiError(r.status_code, err.get("code"), err.get("message"))
        if attempt == max_retries:
            raise ApiError(r.status_code if r is not None else 0, "retry_exhausted", "重试次数用尽")
        delay = min(cap, base * (2 ** attempt)) * random.uniform(0.5, 1.0)
        time.sleep(delay)

if __name__ == "__main__":
    out = call({"model": "uncensored", "max_tokens": 100,
                "messages": [{"role": "user", "content": "回复一个字:好"}]})
    print(out["choices"][0]["message"]["content"])

La formula del backoff è min(cap, base × 2^n) × coefficiente casuale. Il jitter evita collisioni tra client. I codici FATAL non vengono retryati mai.

Limitazione lato client e richieste di diagnostica

Invece di aspettare il 429 per applicare il backoff, è meglio limitare le richieste in anticipo. Il seguente strumento garantisce che il numero di richieste al minuto rimanga sotto il valore impostato ed è sicuro per il multithreading:

import threading
import time

class RateGate:
    """简单的客户端限速:保证一分钟内请求数不超过 limit。"""
    def __init__(self, limit=240):          # 留出余量,低于 300/分钟
        self.limit, self.stamps, self.lock = limit, [], threading.Lock()

    def wait(self):
        while True:
            with self.lock:
                now = time.time()
                self.stamps = [t for t in self.stamps if now - t < 60]
                if len(self.stamps) < self.limit:
                    self.stamps.append(now)
                    return
                sleep_for = 60 - (now - self.stamps[0])
            time.sleep(max(sleep_for, 0.05))

Per il debug, il metodo più pulito è isolarsi dal codice di business e inviare una richiesta minima con curl. L'opzione -i mostra contemporaneamente la riga di stato e le intestazioni di risposta:

curl -i https://api.wushenchaapi.com/v1/chat/completions \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"uncensored","max_tokens":20,"messages":[{"role":"user","content":"ping"}]}'

Se curl funziona ma il codice di business no, il problema è nel tuo codice o nell'ambiente (proxy, variabili d'ambiente, codifica). Se anche curl fallisce, controlla la chiave, il saldo e la rete.

Perché impostare il limite a 240 invece di 300: in caso di distribuzione multi-istanza, ogni istanza applica il proprio limite e la somma può comunque superare il totale; inoltre i ritentativi consumano quota aggiuntiva. Lasciare un margine del 20% è una scelta prudente. Se hai più istanze, dividi equamente la quota totale tra ciascuna istanza o utilizza un contatore condiviso per la gestione centralizzata.

Checklist di troubleshooting

  1. Leggi error.code nel body, non affidarti solo allo stato HTTP.
  2. 401: prefisso della chiave, variabili d'ambiente, verifica se è stata rigenerata.
  3. 400: il JSON è valido? prompt + max_tokens superano 100.000? Il corpo della richiesta supera 8 MB?
  4. 402: saldo e validità del periodo di prova.
  5. 403: input e cronologia contengono contenuti proibiti?
  6. 404: il percorso è /v1/chat/completions o /v1/models?
  7. 429: più istanze condividono la stessa chiave? È stata applicata una limitazione lato client?
  8. 503: è stato applicato il backoff esponenziale? L'intervallo è di almeno qualche secondo?
  9. Timeout: il timeout è sufficiente? Puoi passare allo streaming?
  10. Se tutto è escluso: riproduci il problema con una richiesta minima via curl.

Se ti stai appena connettendo, consulta prima la guida all'integrazione. Per i parametri avanzati, consulta la documentazione.

Usa la checklist: escludi i problemi dall'alto verso il basso, senza saltare. La maggior parte dei problemi

Un consiglio extra: scrivi le conclusioni del troubleshooting nella documentazione del team. In futuro, lo stesso errore ti permetterà di identificare immediatamente la causa.

Domande frequenti

Quanto devo aspettare prima di ritentare dopo un 503?

Bastano pochi secondi. Si consiglia di attendere uno-due secondi al primo tentativo, poi aumentare in modo esponenziale aggiungendo jitter casuale, impostando un numero massimo di ritentativi.

Perché le mie richieste restituiscono sempre 402?

Saldo esaurito o prova 7 giorni scaduta. Ricarica il credito prepagato per ripristinare; il saldo non scadrà.

È possibile aggirare il 403 content_blocked modificando il testo?

Non provare. I contenuti sessuali che coinvolgono minori vengono bloccati in ogni caso, inclusi romanzi e roleplay. I contenuti per adulti normali non attivano questo errore.

Il limite di richieste 429 è per account o per chiave?

Il limite è di 300 richieste al minuto per chiave API. Poiché ogni account ha una sola chiave, è necessario applicare una limitazione congiunta quando più servizi condividono la stessa chiave.

Compila il modulo per ottenere la chiave

Crea un account, copia la chiave e modifica il Base URL. La configurazione è così semplice.