Los errores de la API de Moonshot no se diagnostican solo por el código de estado. Un 429 puede significar sobrecarga del clúster, límite de tasa de la cuenta o saldo insuficiente; un 401 puede deberse a una clave mal escrita o a la mezcla del sitio para China con el sitio internacional. En 2026, la migración del portal y el retiro de modelos antiguos también hicieron crecer los 404.
Este artículo sigue el orden "primero localizar, luego clasificar, después corregir" y desglosa cinco problemas: 401, 404, 429, contexto demasiado largo y timeouts. Incluye código de reintento reutilizable y una lista de datos para abrir un ticket de soporte. Los modelos y precios vigentes se consultan en la página de precios de modelos.
Nota: Moonshot y Kimi son marcas de sus respectivos titulares. Los tipos de error, los niveles de límite de tasa y las fechas de retiro pueden cambiar. Este artículo se basa en la documentación oficial y en casos comunes a octubre de 2026; la documentación oficial es la referencia final.
1. Fija primero tres campos
Al diagnosticar, reúne tres cosas: el código de estado HTTP, el error.type y el identificador de la solicitud. Las respuestas de error de Moonshot suelen incluir error.message y error.type, aunque los campos exactos dependen de la interfaz actual. El identificador puede aparecer en el cuerpo del error, en las cabeceras de la respuesta o en los registros de la consola; su posición cambia entre versiones, así que no supongas una sola fuente.
En los registros, guarda al menos: hora con zona horaria, código de estado, error.type, nombre del modelo, sitio de la Base URL, si es streaming, versión del SDK, número de reintentos, usage e identificador de la solicitud. No registres la clave completa ni prompts con información sensible.
Con esos tres campos puedes decidir si el problema está en la configuración, en la cuenta o en el servidor. Veamos cada categoría.
2. 401: revisa el sitio y después la clave
Moonshot separa el sitio para China y el internacional: el primero usa platform.kimi.com y https://api.moonshot.cn/v1; el segundo usa platform.kimi.ai y https://api.moonshot.ai/v1. Las cuentas, los saldos y las claves son independientes; una clave del sitio para China enviada a la dirección internacional devuelve 401 invalid_authentication_error.
Sigue este orden:
- Confirma que la clave proviene del sitio correspondiente a la Base URL actual, no de otro sitio ni de otra cuenta.
- Verifica que no mezcles claves de la plataforma abierta con claves de otras líneas de producto, como Kimi Code; no son intercambiables.
- Revisa que la cabecera sea
Authorization: Bearer <clave>y que el valor no tenga espacios, saltos de línea ni comillas alrededor. - Confirma que la variable de entorno realmente se cargó; puedes imprimir solo los primeros caracteres de la clave.
- Comprueba si la clave fue eliminada, rotada o si los permisos del proyecto fueron revocados.
- Busca restos de un proxy antiguo, variables de entorno viejas o herramientas de enrutamiento que sobrescriban la solicitud actual.
En cuanto a los tipos, invalid_authentication_error suele indicar formato de clave o sitio incorrecto, y incorrect_api_key_error suele indicar clave ausente o errónea. En ambos casos corrige la credencial antes de reintentar.
3. 404: casi siempre es un modelo retirado, no una interfaz inexistente
La fuente de 404 más ignorada en 2026 es el ciclo de vida de los modelos. El registro de retiros de la página oficial incluye:
- Toda la serie
moonshot-v1, incluidasmoonshot-v1-8k,-32k,-128k,-autoy la versión preliminar con visión, dejó de funcionar el 31 de agosto de 2026; se recomienda migrar akimi-k3. - La serie
kimi-k2, incluidaskimi-k2-0905-preview,kimi-k2-0711-preview,kimi-k2-turbo-previewy la versión de razonamiento, dejó de funcionar el 25 de mayo de 2026. kimi-latestdejó de funcionar el 28 de enero de 2026 ykimi-thinking-previewel 11 de noviembre de 2025.
Otras causas frecuentes de 404:
- El SDK de OpenAI no tiene
base_urlconfigurada, la solicitud va a la dirección predeterminada de OpenAI y el modelo no existe allí. - El nombre del modelo está mal escrito, o el nivel de la cuenta no tiene acceso a ese modelo.
- La ruta tiene
/v1de más o de menos, o el cliente concatena la Base URL con la ruta completa y la duplica. - Los nombres de modelo disponibles difieren entre el sitio para China y el internacional.
Usa la misma clave para listar los modelos y confirmar qué ve realmente la cuenta:
curl "https://api.moonshot.cn/v1/models" \
-H "Authorization: Bearer $MOONSHOT_API_KEY"
No adivines nombres que no aparecen en la lista. Si la lista responde pero el endpoint de chat sigue dando 404, revisa la concatenación de rutas y la configuración del cliente.
4. 429: tres tipos con tratamientos totalmente distintos
El 429 es el error que más se diagnostica mal. Mira primero el error.type:
error.type |
Significado | ¿Se puede reintentar? | Tratamiento |
|---|---|---|---|
engine_overloaded_error |
Sobrecarga del clúster, capacidad ajustada | Sí | Espera según Retry-After y reduce la concurrencia |
rate_limit_reached_error |
Concurrencia, RPM, TPM o TPD de la organización excedidos | En parte | Baja el ritmo, espera o sube el nivel de la cuenta |
exceeded_current_quota_error |
Deuda, saldo insuficiente o cupón vencido | No reintentar | Revisa el saldo y recarga |
Los niveles de límite de Moonshot van de Tier0 a Tier5 según la recarga acumulada; los cupones de recarga normalmente no cuentan para el acumulado. El nivel limita a la vez la concurrencia, las solicitudes por minuto, los tokens por minuto y los tokens por día: los niveles bajos pueden tener concurrencia de un dígito y los altos llegan a cientos; el RPM va de un dígito a cientos y el TPM de cientos de miles a millones. Tier0 además tiene un tope diario de tokens, y al alcanzarlo suele haber que esperar el reinicio del día siguiente.
Errores fáciles de cometer:
- El SDK de OpenAI reintenta automáticamente 408, 409, 429 y 5xx hasta tres veces en total. En una cuenta de nivel bajo, un fallo puede convertirse en varias solicitudes y agotar el RPM. En producción configura
max_retriesde forma explícita. - Herramientas como la búsqueda web tienen su propio límite de QPS, separado del RPM y el TPM del chat; al excederlo también devuelven 429.
- Las solicitudes interrumpidas por un 429 normalmente no se cobran, pero el reintento exitoso sí. No reintentes sin límite solo porque "no cobra".
- Si el límite no coincide con el nivel, confirma si estás usando la clave de otra cuenta.
5. 400: contexto demasiado largo y errores de parámetros
El contexto demasiado largo suele devolver 400 invalid_request_error, con un mensaje que indica que se excedieron los tokens de entrada. Ojo: el criterio es si "entrada más límite de salida" supera la ventana del modelo, no solo la entrada.
Disparadores habituales:
- El historial crece sin límite y la conversación de varios turnos nunca se recorta.
- Se envía un documento completo a un contexto de 1 M y además se fija un límite de salida muy alto.
- La interfaz de archivos recibe más de 100 MB, un archivo vacío o un valor de
purposefuera de la lista permitida. - La salida activa
content_filter; este filtro también puede dispararse por la salida del modelo, no solo por la entrada.
El orden de corrección es: estima primero los tokens de entrada y reserva espacio para la salida; divide y resume documentos largos conservando citas; aplica una ventana deslizante a las conversaciones; usa llamadas a herramientas para salidas estructuradas y reducir texto largo inútil.
Además, finish_reason=length no es un error, sino que la salida llegó al límite. Si necesitas resultados más largos, pide por tramos o usa capacidad de continuación; no subas el límite por encima del máximo permitido por el modelo.
6. Timeouts, 499 y streaming
El gateway de Moonshot tiene un límite de espera para solicitudes no streaming; la documentación oficial menciona que un 504 puede aparecer después de 900 segundos. La generación de textos largos, el análisis de documentos extensos y los agentes de código son los casos más propensos.
Sigue este orden:
- Cambia de no streaming a streaming con
stream=Truepara que la conexión siga recibiendo datos. - Configura un timeout de conexión corto y un timeout de lectura acorde al tiempo máximo de generación; no uses los valores predeterminados del SDK.
- Revisa si el proxy corporativo, el gateway o una herramienta de enrutamiento local corta la conexión antes de tiempo; esa interrupción puede verse como 499
client_closed_request. - Controla la longitud de cada generación con el límite de salida y divide las tareas muy largas.
- En streaming, observa la latencia del primer token; un aumento repentino del TTFT suele indicar congestión upstream o un prompt más largo.
- Registra el identificador y la duración de cada timeout para distinguir si es lento el modelo, la red o el proxy.
El streaming no reduce el precio unitario, pero evita el consumo duplicado de "esperar al timeout y reintentar". No reutilices un timeout de lectura corto del modo no streaming, o el cliente cortará la conexión mientras el modelo todavía genera con normalidad.
7. Cómo escribir reintentos y retroceso
Los reintentos solo sirven para errores transitorios. No reintentes automáticamente 401, 403, 404, seguridad de contenido ni saldo insuficiente; clasifica primero el 429; los 5xx sí admiten retroceso. Si la operación ya produjo efectos secundarios, usa una clave de idempotencia o consulta el estado antes de repetir.
import random
import time
from openai import OpenAI, APIStatusError, RateLimitError
client = OpenAI(
api_key="tu-clave",
base_url="https://api.moonshot.cn/v1",
max_retries=0, # desactiva los reintentos automáticos del SDK
)
RETRYABLE_TYPES = {"engine_overloaded_error", "server_error",
"server_unavailable", "client_closed_request"}
def ask(prompt: str, retries: int = 4) -> str:
for attempt in range(retries):
try:
resp = client.chat.completions.create(
model="kimi-k3",
messages=[{"role": "user", "content": prompt}],
max_completion_tokens=1024,
)
return resp.choices[0].message.content
except RateLimitError as exc:
body = exc.body or {}
etype = (body.get("error") or {}).get("type", "")
if etype == "exceeded_current_quota_error":
raise RuntimeError("Saldo o cuota insuficientes; recarga primero")
if etype == "rate_limit_reached_error":
raise RuntimeError("Límite de la cuenta; reduce la concurrencia o sube de nivel")
wait = min(2 ** attempt, 20) + random.random()
print(etype or "overloaded", "espera", round(wait, 1), "segundos")
time.sleep(wait)
except APIStatusError as exc:
if exc.status_code in (401, 403, 404):
raise
if exc.status_code >= 500:
time.sleep(min(2 ** attempt, 20) + random.random())
else:
raise
raise RuntimeError("Se agotaron los reintentos")
print(ask("Explica cuándo corresponde reintentar"))
Si hay cabecera Retry-After, espera según ese valor y añade una variación aleatoria para evitar que varias instancias reintenten a la vez y provoquen otra congestión. Limita el número de reintentos y registra el fallo final en una alerta.
8. Qué preparar antes de pedir soporte
- Hora del incidente, con zona horaria y año, precisa al segundo.
- Identificador de la solicitud,
idde la respuesta y campos deusage. - Nombre del modelo, Base URL, sitio (China o internacional) y si era streaming.
- Código de estado HTTP,
error.typey mensaje de error completo. - Versión del SDK y del cliente, configuración de reintentos, y si pasó por un proxy o gateway.
- Una solicitud mínima reproducible; basta con un comando curl.
- Registro de facturación o consumo para comprobar si hubo doble cobro.
- Registros anonimizados, sin claves, datos de usuarios ni prompts sensibles.
Reproduce primero con un curl directo y luego envía por separado los resultados de la conexión directa y del gateway; eso acorta mucho el tiempo de localización.
Preguntas frecuentes
¿Un reintento de 429 cobra dos veces?
Las solicitudes rechazadas con 429 normalmente no se cobran; el reintento exitoso se cobra como una solicitud normal. El riesgo real es que el reintento automático del SDK convierta una solicitud de negocio en varias y aumenten a la vez el número de solicitudes y el costo.
Ayer funcionaba un modelo y hoy devuelve 404, ¿por qué?
Revisa el registro de retiros de la página oficial de modelos. La serie moonshot-v1 dejó de funcionar el 31 de agosto de 2026; las series kimi-k2 y kimi-latest también dejaron de recibir mantenimiento. Migra a kimi-k3 según la recomendación oficial.
El 429 dice saldo insuficiente, ¿igual conviene reintentar con espera?
No. exceeded_current_quota_error corresponde a saldo o cuota de la cuenta; reintentar no lo recupera. Revisa el saldo, el estado de deuda y la vigencia de los cupones.
Ya uso streaming, ¿por qué sigue apareciendo timeout?
El streaming reduce la espera del primer paquete, pero no implica que la conexión nunca se corte. Revisa el idle timeout del proxy, el timeout de lectura, el límite de salida y la estabilidad de la red; también puede ocurrir que el upstream pase mucho tiempo sin emitir tokens y un dispositivo intermedio cierre la conexión.
La conexión directa funciona y el gateway falla, ¿cómo identificar al responsable?
Envía la misma clave, el mismo modelo y la misma solicitud por conexión directa y por gateway, y compara código de estado, error.type, identificador y duración. Si la directa funciona y el gateway falla, revisa la ruta, la autenticación, los timeouts y la configuración de reintentos del gateway.
Próximos pasos
Crea una clave de prueba en ZSQH AI Gateway, practica una vez cada caso de 401, 404, 429 y timeout, y luego conecta el monitoreo de producción. Los modelos disponibles y la facturación se rigen por la página de precios de modelos.
Lecturas relacionadas:
