500 y 502 significan un fallo, no un límite. Eso los convierte en la única clase de errores de esta familia que merece reintentos casi inmediatos, a diferencia de 429, que es tu propio límite de velocidad, y 529, que indica que el proveedor está saturado. Reintentar el incorrecto de los tres convierte un incidente pequeño en tu propio incidente.
El error
// Straight from the model provider (HTTP 500)
{
"type": "error",
"error": { "type": "api_error", "message": "Internal server error" }
}
// From a gateway or proxy in between (HTTP 502)
{
"error": {
"message": "Failed to reach upstream provider",
"type": "upstream_error",
"code": "upstream_error",
"param": null
}
}Causas y soluciones de un vistazo
| Causa | Solución |
|---|---|
| Fallo transitorio del proveedor | Reintenta con backoff exponencial y jitter, con un máximo de ~5 intentos. |
| Conexión aceptada, pero nunca respondió | No es un error, sino un bloqueo. Limita por separado el tiempo hasta el primer byte y la duración total. |
| Un intermediario que devuelve su propio 502 | No tiene nada que ver con el modelo. Comprueba si el cuerpo tiene el formato del proveedor o el de un proxy. |
| Reintentar a ciegas durante un incidente real | Limita los intentos y aplica backoff; de lo contrario, tus reintentos pasarán a formar parte de la interrupción del servicio. |
Distingue 500 de 529 y 429 antes de elegir una solución
429 es un límite de velocidad que estás superando: reduce la velocidad. 529 significa que el proveedor está al límite de su capacidad: aplica backoff mucho más intenso y durante más tiempo. 500/502 es un fallo, normalmente breve y a menudo específico de una solicitud. Solo el tercero merece reintentos rápidos, y tratar los tres igual es la razón por la que los bucles de reintento empeoran los incidentes.
Reintenta los 5xx, nunca los 4xx
Backoff exponencial con jitter, con un máximo de cinco intentos. El mismo helper funciona para todos los proveedores: un 400 o 422 fallará igual en el siguiente intento, por lo que reintentarlo solo añade latencia para llegar al mismo error.
import time, random
from openai import OpenAI, APIStatusError
client = OpenAI(base_url="https://api.kunavo.com/v1", api_key="sk-kn-...")
def with_backoff(fn, max_retries=5):
for attempt in range(max_retries):
try:
return fn()
except APIStatusError as e:
if e.status_code not in (429, 500, 529):
raise # don't retry auth/validation errors
retry_after = e.response.headers.get("retry-after")
delay = float(retry_after) if retry_after else min(2 ** attempt, 30)
time.sleep(delay + random.uniform(0, 0.5)) # jitter avoids herds
raise RuntimeError("retries exhausted")
resp = with_backoff(lambda: client.chat.completions.create(
model="claude-sonnet-5",
messages=[{"role": "user", "content": "ping"}],
max_tokens=32,
))
print(resp.choices[0].message.content)Limita por separado el tiempo hasta el primer byte y la duración total
Un único tiempo de espera para toda la solicitud no puede distinguir una generación larga de una conexión inactiva. Establece un plazo breve para el primer byte y otro amplio para el resto; así, un bloqueo falla rápidamente, mientras que una respuesta realmente lenta puede continuar.
Registra el estado y la latencia de cada intento
Sin registros por intento, un incidente del proveedor y tu propio tiempo de espera parecen idénticos a posteriori. El código de estado, la latencia y el número de intento bastan para distinguirlos a la mañana siguiente.
Si llamas a través de Kunavo
En septiembre de 2026, todos los modelos Claude de Kunavo se sirven a través de un único canal ascendente, por lo que un 5xx de ese canal no se reintenta dentro de la solicitud: te llega como un 502 con el mensaje “Upstream provider error” (tipificado como api_error en /v1/messages), y la solicitud se registra con coste cero. El reintento dentro de la solicitud de Kunavo solo se ejecuta para un modelo con un segundo canal configurado: un tiempo de espera agotado, un 5xx, un 429 o el rechazo de la propia clave ascendente de Kunavo se reintenta entonces en ese canal antes de llegar a ti, en /v1/messages, /v1/responses y los modelos Claude en /v1/chat/completions. Un stream se mantiene en espera hasta que llega su primer contenido, por lo que un error dentro de un stream que aún no ha comenzado también se reintenta; una vez que el contenido fluye, un fallo a mitad del stream debes gestionarlo tú. En cualquier caso, mantén en tu lado la política de reintentos de esta página. El enrutamiento detrás de ese comportamiento se describe en nuestra guía de la puerta de enlace de IA.
Preguntas frecuentes
¿Se me factura una solicitud que devuelve 500?
En Kunavo, no: las solicitudes fallidas se registran con coste cero. La facturación directa con un proveedor varía, pero normalmente un 5xx no se cobra.
¿Reintentar un 500 puede producir dos finalizaciones?
Sí. Una solicitud puede fallar después de que el modelo ya haya generado contenido. Si el trabajo tiene efectos secundarios, hazlo idempotente en tu capa antes de añadir reintentos.
¿Cuál es la diferencia en una línea entre 500, 502 y 529?
500 significa que el proveedor está fallando, 502 que algo situado delante no consigue contactar con el proveedor y 529 que el proveedor está al límite de su capacidad: reintenta pronto los dos primeros y mucho más tarde el tercero.
Guías relacionadas
- Claude API 529 overloaded_error — qué es y cómo superarlo
- Claude API 429 rate_limit_error: causas y una solución eficaz
Encontrarás más detalles sobre el significado de los errores en referencia de errores; obtener una clave lleva un minuto mediante registro y la guía de autenticación.