Un errore 429 di OpenRouter non indica necessariamente che il tuo account abbia esaurito un limite. Potrebbe essere il provider upstream selezionato a limitare le richieste. Prima di intervenire, salva una risposta di errore completa: stato HTTP, header e corpo JSON rivelano quale limite devi davvero risolvere.
Prima di intervenire, analizza una risposta 429
Non acquistare crediti, non sostituire la chiave e non aggiungere retry finché non hai classificato l'errore. I campi tipizzati di OpenRouter e gli header della risposta sono più affidabili del messaggio leggibile, che può includere testo inoltrato da un provider upstream.
| Indizio | Origine più probabile | Cosa fare |
|---|---|---|
HTTP 429 con X-RateLimit-Limit, X-RateLimit-Remaining e X-RateLimit-Reset | Limite della piattaforma OpenRouter | Attendi il reset, poi riduci frequenza o concorrenza delle richieste |
error.metadata.error_type è rate_limit_exceeded, con dettagli del provider come provider_code | Provider upstream | Attendi, consenti un altro provider oppure usa un fallback del modello |
È presente Retry-After | Tutti i provider tentati hanno fornito un'indicazione per il retry | Attendi l'intervallo indicato prima del tentativo successivo |
| HTTP 402 | Saldo insufficiente o tetto di credito per chiave esaurito | Aggiungi credito o modifica il tetto della chiave: il backoff dei retry non risolve il problema |
HTTP 200, seguito da un errore SSE e finish_reason: "error" | Errore avvenuto dopo l'avvio dello streaming | Considera fallito lo stream e controlla il tipo di errore incorporato |
La documentazione su errori e debugging di OpenRouter definisce l'involucro con error.code, error.message e l'opzionale error.metadata, incluso error_type = "rate_limit_exceeded"; specifica inoltre che le risposte riuscite normalmente non includono X-RateLimit-*. Il sovraccarico del provider è un caso distinto, tipizzato come provider_overloaded e normalmente associato a 503.
Come risolvere un 429 a livello OpenRouter
Un 429 generato da OpenRouter dipende dalla quota della piattaforma associata all'account e alla classe del modello. In base alla documentazione ufficiale sui limiti di frequenza, verificata il 31 luglio 2026, le varianti gratuite che terminano con :free hanno limiti sia al minuto sia giornalieri.
| Quota dei modelli gratuiti | Limite attuale |
|---|---|
| Richieste al minuto | 20 RPM |
| Richieste giornaliere con meno di $10 di acquisti di credito complessivi | 50 RPD |
| Richieste giornaliere con almeno $10 di acquisti di credito complessivi | 1,000 RPD |
La politica dei limiti chiarisce che account o chiavi aggiuntivi non aumentano la capacità regolata globalmente: sostituire una chiave valida, quindi, non azzera un limite di frequenza della piattaforma.
Usa l'endpoint GET /api/v1/key per controllare utilizzo e limiti di credito:
curl https://openrouter.ai/api/v1/key \
-H "Authorization: Bearer $OPENROUTER_API_KEY"
Quando il 429 arriva dalla piattaforma, consulta l'header di reset nella risposta di errore e procedi in questo ordine:
- Interrompi i retry immediati e attendi fino a
X-RateLimit-Reset. - Riduci le richieste concorrenti, non solo le richieste al secondo. Un picco di worker paralleli può superare il limite prima che uno di loro riceva il primo 429.
- Metti il lavoro in coda dietro un limitatore condiviso, così tutti i worker non si risvegliano e riprovano nello stesso istante.
- Se il carico non rientra nella quota dei modelli gratuiti, sposta quel traffico su una variante a pagamento appropriata.
Un saldo negativo o un tetto di credito per chiave esaurito dovrebbe produrre un 402, mentre un provider upstream può comunque restituire 429 anche a un account con credito disponibile. La guida ai prezzi di OpenRouter tratta separatamente costi e crediti.
Come gestire il 429 "Provider Returned Error"
Un 429 restituito dal provider significa che OpenRouter ha raggiunto un provider di inferenza upstream che, in quel momento, non poteva accettare la richiesta. Cerca il valore tipizzato del rate limit e i metadati del provider: aggiungere credito a OpenRouter non crea capacità presso quel provider.
La documentazione ufficiale sui limiti spiega che il routing potrebbe aver già tentato provider alternativi prima di restituire l'errore e aggiunge Retry-After quando ogni provider provato ha fornito un suggerimento di retry. In pratica, conviene:
- Rispettare
Retry-After, invece di rigenerare subito la stessa richiesta. - Rimuovere vincoli troppo rigidi sui provider se lasciano disponibile una sola rotta congestionata.
- Verificare che il fallback del provider sia consentito per la richiesta.
- Configurare un fallback del modello quando completare il compito conta più dell'uso del modello esatto.
Un utente Zed con credito disponibile ha incontrato un limite upstream su moonshotai/kimi-k2:free, e rigenerare la chiave non è servito. Un contributor di Zed ha spiegato:
“Questo non è un errore di Zed: è OpenRouter che ti sta comunicando che il provider upstream in uso sta applicando un rate limit.” Fonte: zed-industries/zed issue #35153
Rispetta un Retry-After breve; ricorri a un fallback tra i modelli gratuiti solo quando completare il lavoro è più importante di mantenere il modello esatto.
Se l'errore compare in Janitor AI, Zed o SillyTavern
Conserva l'errore originale, evita rigenerazioni ripetute e modifica il modello o la rotta consentita in caso di errori lato provider. Reinserisci una chiave soltanto per correggere il salvataggio nel client: non ripristina la capacità disponibile.
Retry senza innescare un ciclo di 429
Riprova solo in caso di rate limit, limita il numero di tentativi e dai priorità al ritardo richiesto dal server. Se non viene fornita alcuna indicazione, applica un backoff esponenziale con limite massimo e jitter, così i client paralleli non si sincronizzano in un nuovo picco di richieste.
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
function retryDelayMs(response, attempt) {
const retryAfter = response.headers.get("retry-after");
if (retryAfter) {
const seconds = Number(retryAfter);
if (Number.isFinite(seconds)) return Math.max(0, seconds * 1000);
const dateMs = Date.parse(retryAfter);
if (Number.isFinite(dateMs)) return Math.max(0, dateMs - Date.now());
}
const capMs = 30_000;
const exponentialMs = Math.min(capMs, 1000 * 2 ** attempt);
return Math.random() * exponentialMs; // Full jitter
}
async function createChatCompletion(body, maxAttempts = 4) {
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
const response = await fetch(
"https://openrouter.ai/api/v1/chat/completions",
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify(body),
},
);
const raw = await response.text();
let payload;
try {
payload = raw ? JSON.parse(raw) : null;
} catch {
payload = null;
}
if (response.ok) return payload;
const isRateLimit =
response.status === 429 ||
payload?.error?.metadata?.error_type === "rate_limit_exceeded";
if (!isRateLimit || attempt === maxAttempts - 1) {
const error = new Error(payload?.error?.message || raw || `HTTP ${response.status}`);
error.status = response.status;
error.details = payload?.error;
throw error;
}
await sleep(retryDelayMs(response, attempt));
}
}
Questa funzione gestisce le risposte non in streaming; il controllo della concorrenza tramite coda condivisa o token bucket va implementato all'esterno, per evitare che molti worker in attesa ripartano insieme.
Quando gli eventi Server-Sent Events iniziano con HTTP 200, lo stato non può più diventare 429. La documentazione sugli errori di OpenRouter indica che un errore successivo arriva nello stream con un errore e finish_reason: "error"; considera quindi fallito il completamento e riprova solo se il tipo incorporato è rate_limit_exceeded. Non restituire il testo già accumulato come successo, a meno che l'applicazione non supporti esplicitamente risultati parziali.
FAQ
Cosa significa "429 provider returned error" in OpenRouter?
Un provider di inferenza upstream ha rifiutato la richiesta per un proprio limite di frequenza o capacità. Confermalo tramite error.metadata.error_type e i metadati del provider.
Perché ricevo un 429 di OpenRouter anche se ho ancora credito?
Un account con credito può ricevere un 429 lato provider; un saldo insufficiente o un tetto di credito per chiave è normalmente un 402.
Creare una nuova chiave API OpenRouter azzera il rate limit?
No. Le chiavi aggiuntive non aumentano i limiti regolati globalmente; sostituiscine una solo per risolvere problemi di autenticazione o salvataggio nel client.
Quanto devo aspettare prima di riprovare con OpenRouter?
Usa Retry-After quando è presente. Per un limite della piattaforma, usa X-RateLimit-Reset; se non hai nessuna delle due indicazioni, usa un backoff esponenziale con limite massimo e jitter, con un numero contenuto di tentativi.
OpenRouter può restituire HTTP 200 e fallire comunque con un 429?
Sì, quando lo streaming è già iniziato. Lo stato HTTP rimane 200, mentre lo stream SSE segnala un errore e termina con finish_reason: "error"; controlla il tipo di errore incorporato per stabilire se si trattava di un rate limit.