Un error 429 en OpenRouter no implica necesariamente que hayas agotado el límite de tu cuenta. También puede indicar que el proveedor upstream seleccionado está limitando las solicitudes. Antes de tocar nada, guarda una respuesta fallida completa: el estado HTTP, las cabeceras y el cuerpo JSON revelan qué límite debes resolver.
Antes de cambiar nada, analiza una respuesta 429
Identifica el origen del fallo antes de comprar créditos, sustituir la clave o añadir reintentos. Los campos tipados de OpenRouter y las cabeceras de la respuesta ofrecen una señal mucho más fiable que el mensaje legible, que puede incluir texto reenviado por un proveedor upstream.
| Indicio | Origen más probable | Siguiente paso |
|---|---|---|
HTTP 429 junto con X-RateLimit-Limit, X-RateLimit-Remaining y X-RateLimit-Reset | Límite de la plataforma OpenRouter | Espera hasta el reinicio y reduce la tasa de solicitudes o la concurrencia |
error.metadata.error_type es rate_limit_exceeded, con datos del proveedor como provider_code | Proveedor upstream | Espera, permite otro proveedor o usa un fallback de modelo |
Está presente Retry-After | Todos los proveedores intentados proporcionaron una indicación de reintento | Espera ese intervalo antes del siguiente intento |
| HTTP 402 | Saldo insuficiente o límite de crédito por clave agotado | Añade crédito o modifica el límite de la clave; el backoff no lo solucionará |
HTTP 200 seguido de un error SSE y finish_reason: "error" | Fallo después de que empezara el streaming | Trata el stream como fallido e inspecciona el tipo de error integrado |
La referencia de errores y depuración de OpenRouter define la estructura con error.code, error.message y el campo opcional error.metadata, incluido error_type = "rate_limit_exceeded". También indica que las respuestas correctas normalmente no incluyen X-RateLimit-*. La sobrecarga del proveedor se tipa por separado como provider_overloaded y normalmente se asigna a un 503.
Cómo resolver un 429 de OpenRouter
Un 429 generado por OpenRouter depende de la cuota de la plataforma asociada a la cuenta y a la clase de modelo. Según la documentación oficial sobre límites de tasa, verificada el 31 de julio de 2026, las variantes de modelos gratuitos terminadas en :free tienen límites tanto por minuto como diarios.
| Cuota de modelos gratuitos | Límite actual |
|---|---|
| Solicitudes por minuto | 20 RPM |
| Solicitudes diarias con menos de $10 en compras de crédito acumuladas | 50 RPD |
| Solicitudes diarias con al menos $10 en compras de crédito acumuladas | 1,000 RPD |
La política de límites indica que las cuentas o claves adicionales no aumentan una capacidad gestionada globalmente. Por tanto, reemplazar una clave válida no reinicia un límite de tasa de la plataforma.
Usa el endpoint GET /api/v1/key para consultar el uso y los límites de crédito:
curl https://openrouter.ai/api/v1/key \
-H "Authorization: Bearer $OPENROUTER_API_KEY"
Ante un 429 de la plataforma, consulta la cabecera de reinicio incluida en la respuesta de error y aplica estas medidas en este orden:
- Detén los reintentos inmediatos y espera hasta
X-RateLimit-Reset. - Reduce las solicitudes simultáneas, no solo las solicitudes por segundo. Una ráfaga de workers en paralelo puede superar el límite antes de que alguno reciba el primer 429.
- Encola el trabajo detrás de un limitador compartido para evitar que todos los workers se despierten y reintenten a la vez.
- Si la carga de trabajo no cabe en la cuota de modelos gratuitos, mueve ese tráfico a una variante de modelo de pago adecuada.
Un saldo negativo o un límite de crédito por clave agotado debería generar un 402, mientras que un proveedor upstream puede devolver un 429 incluso a una cuenta con fondos. La guía de precios de OpenRouter aborda por separado las cuestiones de costes y créditos.
Cómo corregir el 429 «Provider Returned Error»
Un 429 devuelto por un proveedor significa que OpenRouter llegó a un proveedor upstream de inferencia que no podía aceptar la solicitud en ese momento. Busca el valor tipado de límite de tasa y los metadatos del proveedor: añadir crédito a OpenRouter no crea capacidad en ese proveedor.
La referencia oficial de límites señala que el enrutamiento puede haber probado proveedores alternativos antes de devolver el error, y añade Retry-After cuando todos los proveedores intentados han proporcionado una indicación de reintento. En la práctica, conviene:
- Respetar
Retry-Afteren lugar de regenerar enseguida la misma solicitud. - Eliminar restricciones de proveedor demasiado estrictas si dejan una única ruta congestionada.
- Comprobar que el fallback de proveedor esté permitido para la solicitud.
- Configurar un fallback de modelo cuando completar la tarea importe más que utilizar exactamente ese modelo.
Un usuario de Zed con saldo disponible encontró un límite upstream en moonshotai/kimi-k2:free, y regenerar la clave no sirvió de nada. Un colaborador de Zed explicó:
«No es un error de Zed; OpenRouter te está diciendo que el proveedor upstream que usas te está aplicando un límite de tasa». Fuente: zed-industries/zed issue #35153
Respeta un Retry-After corto; recurre a un fallback de modelo gratuito solo cuando terminar la tarea importe más que mantener el modelo exacto.
Si el error aparece en Janitor AI, Zed o SillyTavern
Conserva el error sin procesar, evita regenerar repetidamente y cambia el modelo o la ruta permitida cuando el fallo proceda del proveedor. Vuelve a introducir una clave únicamente para corregir el almacenamiento del cliente: no restablece la capacidad.
Reintentos sin caer en un bucle de errores 429
Reintenta únicamente los fallos por límite de tasa, limita el número de intentos y da prioridad a la espera indicada por el servidor. Si no hay una indicación de reintento, usa backoff exponencial limitado con jitter para que los clientes en paralelo no se sincronicen y generen otra ráfaga.
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));
}
}
Esta función gestiona respuestas sin streaming. Coloca fuera de ella el control de concurrencia mediante una cola compartida o un token bucket, para que muchos workers en espera no puedan reiniciarse todos juntos.
Cuando los Server-Sent Events ya han comenzado con HTTP 200, el estado no puede pasar a 429. La referencia de errores de OpenRouter indica que un fallo posterior llega dentro del stream con un error y finish_reason: "error". Marca la finalización como fallida y reintenta solo si el tipo integrado es rate_limit_exceeded. No devuelvas el texto acumulado como éxito salvo que la aplicación admita explícitamente resultados parciales.
Preguntas frecuentes
¿Qué significa el error 429 «provider returned error» en OpenRouter?
Un proveedor upstream de inferencia rechazó la solicitud debido a su propio límite de tasa o capacidad. Confírmalo mediante error.metadata.error_type y los metadatos del proveedor.
¿Por qué recibo un 429 de OpenRouter si todavía tengo créditos?
Una cuenta con saldo puede recibir un 429 del lado del proveedor. En cambio, un saldo insuficiente o un límite de crédito por clave normalmente genera un 402.
¿Crear una nueva clave de API de OpenRouter reinicia el límite de tasa?
No. Las claves adicionales no aumentan los límites gestionados globalmente; sustituye una solo para resolver problemas de autenticación o almacenamiento en el cliente.
¿Cuánto debo esperar antes de reintentar OpenRouter?
Usa Retry-After cuando esté presente. Para un límite de plataforma, usa X-RateLimit-Reset; si no dispones de ninguna de estas indicaciones, aplica backoff exponencial limitado con jitter y un número máximo de intentos bajo.
¿Puede OpenRouter devolver HTTP 200 y aun así fallar con un 429?
Sí, cuando el streaming ya ha comenzado. El estado HTTP sigue siendo 200, mientras que el stream SSE informa de un error y termina con finish_reason: "error". Inspecciona el tipo de error integrado para determinar si se trató de un límite de tasa.