- Errores de solicitud de API — la respuesta HTTP a una llamada síncrona a la API (autenticación, facturación, solicitudes mal formadas, recursos inexistentes). Consulta Errores de solicitud de API.
- Códigos de fallo de predicción — la solicitud se aceptó y se puso en cola, pero la predicción en sí terminó con
status: "failed". El fallo lo describe el objetoerrorde la predicción, que obtienes en los endpoints de estado de la predicción, en las entregas de webhook y en el endpoint de resultado. Consulta Códigos de fallo de predicción.
Códigos de fallo de predicción
Una predicción fallida lleva un objetoerror:
Las predicciones fallidas no se cobran; los créditos reservados para la solicitud se liberan.
Una predicción que no ha fallado lleva
error: null. Consulta la Nota de migración si integraste antes del 17 de agosto de 2026.
Dónde te llega el error
El mismo objetoerror se publica en todos los canales, así que puedes leerlo allí donde ya miras:
Leer un fallo desde el endpoint de resultado
Pedir la salida de una predicción que falló devuelve un400 con el fallo que la provocó, bajo el código de nivel de solicitud PREDICTION_FAILED:
error.codeesPREDICTION_FAILED, un error de solicitud de API que significa «la predicción cuya salida pediste no produjo ninguna»;error.detailses el objetoerrorpropio de la predicción: idéntico a lo que/statusinforma para esa misma solicitud, de modo que los dos endpoints nunca pueden discrepar sobre por qué falló. Ramifica tu código conerror.details.reasonyerror.details.retryable.
error.message repite el mensaje de la predicción, así que un cliente que solo lea el mensaje de nivel superior sigue obteniendo algo útil.
Dos timestamps, dos significados. El timestamp de nivel superior indica cuándo se generó esta respuesta HTTP; error.details.timestamp indica cuándo falló la predicción. En una predicción que consultas días después, se separan por días. Lee el interior siempre que te refieras al fallo.
Las bibliotecas cliente oficiales desempaquetan esto por ti: result() lanza un error cuyos code, reason y retryable son los de la propia predicción, idénticos a los que lanza subscribe() para ese mismo fallo.
Una predicción que sigue en cola o en ejecución, o una que se canceló, sigue devolviendo el mismo 400 genérico de siempre.
Cómo decidir si reintentar
Leeretryable. Responde exactamente a una pregunta —¿enviar esta misma solicitud otra vez dará un resultado distinto?— y es independiente del code: un mismo code puede ser reintentable en un fallo y no serlo en otro.
retryable es opcional. Cuando está ausente, recurre al valor por defecto por code de la tabla siguiente. Ese era el comportamiento de Sunra antes de que existiera este campo, así que recurrir a él siempre es seguro; simplemente es menos preciso.
code
reason
reason nombra la causa concreta detrás de code. Úsalo para métricas, enrutamiento y diagnóstico de soporte; usa retryable para decidir si reintentar.
Cada reason publicada hoy tiene su propia sección más abajo, y su ancla es la propia reason —#input_fetch_failed, #moderation_blocked, etc.—, de modo que un informe de errores puede enlazar directamente a su significado.
input_validation_failed
code: invalid_input · retryable: false
La solicitud no superó la validación de schema o de parámetros propia de Sunra. El message nombra el campo problemático.
Qué hacer: corrige el campo indicado. La misma solicitud seguirá fallando.
provider_rejected_input
code: invalid_input · retryable: false
El proveedor del modelo rechazó uno o más parámetros de entrada. Cuando nos dice cuáles, el message lo recoge; algunos proveedores solo informan de que la entrada era inaceptable, y en ese caso lo decimos tal cual en lugar de suponerlo.
Qué hacer: revisa tus parámetros frente al schema del modelo: un valor fuera de rango, una combinación no admitida, una relación de aspecto o una duración que el modelo no acepta.
input_fetch_failed
code: invalid_input · retryable: false o true
No se pudo descargar un archivo de entrada referenciado por URL. Es la única reason cuyo retryable varía de verdad, así que lee el campo en lugar de darlo por hecho:
false: el host nos rechazó, con un4xx, una dirección desde la que no tenemos permitido descargar, una redirección o un archivo que supera el límite de tamaño;true: el host estuvo momentáneamente inaccesible, con un5xx, un tiempo de espera agotado o un fallo de DNS.
message reproduce la URL que enviaste para que sepas qué entrada falló, con su query string eliminada, de modo que las credenciales de una presigned URL nunca se te devuelven:
retryable sea false, comprueba que la URL sea accesible públicamente y que un enlace presigned no haya caducado. Cuando sea true, reintenta.
moderation_blocked
code: unsafe_content · retryable: false
Bloqueado por el sistema de seguridad de contenido del proveedor del modelo: puede ser el prompt y el material de entrada, o la salida generada.
Qué hacer: cambia el prompt o el material. Reenviar el mismo contenido se volverá a bloquear.
provider_rate_limited
code: service_provider_error · retryable: true
El proveedor del modelo está limitando la tasa de solicitudes.
Qué hacer: reintenta con backoff o enruta a otro modelo.
provider_unavailable
code: service_provider_error · retryable: true
El proveedor del modelo no pudo atender la solicitud.
Qué hacer: reintenta más tarde o enruta a otro modelo.
provider_timeout
code: task_timeout · retryable: true
La predicción no se completó dentro del tiempo permitido.
Qué hacer: reintenta; un momento de menos carga, o una solicitud más pequeña (menos duración, menos resolución), mejora las probabilidades.
provider_account_error
code: internal_server_error · retryable: false
Nuestra propia cuenta con el proveedor del modelo tiene un problema: facturación, credenciales o una cuota permanente. La culpa es nuestra, no de tu entrada.
Qué hacer: nada por tu parte; reintentar no ayudará y recibimos una alerta automática. Enruta a otro modelo si necesitas esa capacidad ahora mismo.
endpoint_misconfigured
code: internal_server_error · retryable: false
Este endpoint de modelo está mal configurado de nuestro lado.
Qué hacer: nada por tu parte; reintentar no ayudará y recibimos una alerta automática. Contacta con soporte indicando el request_id si es urgente.
queue_enqueue_failed
code: internal_server_error · retryable: true
La predicción no se pudo poner en la cola.
Qué hacer: vuelve a enviar la solicitud.
reaped_stalled
code: internal_server_error · retryable: true
La predicción se quedó bloqueada y fue terminada.
Qué hacer: vuelve a enviar la solicitud.
Valores desconocidos
Tantocode como reason son conjuntos abiertos. Se añaden valores nuevos a medida que clasificamos más fallos, sin anuncio de cambio incompatible. Tu integración no debe fallar, descartar el error ni rechazar el payload cuando encuentre un valor que no reconozca.
reasondesconocido: trátalo como sireasonestuviera ausente y decide conretryable(o con el valor por defecto porcode). Guarda el valor original en tus registros: es la vía más rápida para que soporte identifique el fallo.codedesconocido: trátalo comointernal_server_error. Hay un valor centinela que conviene conocer por su nombre:unknown_error_code, que Sunra emite cuando una predicción falló pero no se pudo recuperar ninguna clasificación para ella.
Nota de migración: error es null cuando no hay error
En vigor desde el 17 de agosto de 2026. El objetoerror tiene una única representación en todos los canales. Han desaparecido tres diferencias entre ellos:
erroresnullcuando la predicción no ha fallado.GET /v1/predictions/{prediction_id}respondía con un objeto vacío —"error": {}— en toda predicción con éxito, en cola o cancelada. Ahora responde"error": null, que es lo que el endpoint de estado de la cola ya hacía. Si compruebas si está vacío (Object.keys(response.error).length === 0), sustitúyelo por una comprobación de nulo (response.error === null).- Un fallo siempre lleva un
codey unmessageno vacíos. Cuando un fallo registró algo que no podemos clasificar, ahora obtienes el centinelaunknown_error_codey un mensaje genérico, en lugar de un campo ausente, vacío o que no es una cadena. - Los fallos registrados como texto plano te llegan como texto. Un puñado de predicciones de abril de 2026 guardaron su error como una cadena suelta.
GET /v1/predictions/{prediction_id}lo descartaba y el endpoint de estado de la cola lo sustituía por el mensaje centinela; ahora ambos lo publican comomessagebajocode: "unknown_error_code".
error ya estaba en todas y cada una de estas respuestas, y lo único que cambió fue su valor. Las entregas de webhook no se tocan —eran la forma hacia la que convergieron los demás canales— y error sigue estando ausente en una entrega succeeded en lugar de enviarse como null.
Ventana de compatibilidad. No hay periodo de emisión doble; la API dejó de producir "error": {} en esa fecha. Si reproduces o reprocesas payloads que capturaste antes, trata null y {} como lo mismo hasta que esos datos almacenados caduquen.
Cambio próximo: algunos fallos recibirán un code más específico
Hoy una parte importante de los fallos se reporta como service_provider_error, incluidos muchos que no son transitorios ni culpa del proveedor. A medida que clasificamos proveedores uno a uno, esos fallos pasan al code que realmente los describe:
- que un proveedor rechace tu entrada de forma determinista pasa a ser
invalid_input(antesservice_provider_error); - un problema del lado de Sunra, como un endpoint mal configurado o nuestra propia cuenta con el proveedor, pasa a ser
internal_server_error(antesservice_provider_error); - un archivo de entrada que no pudimos descargar pasa a ser
invalid_input(antesinternal_server_error).
code: los cinco valores anteriores siguen siendo el conjunto completo de códigos clasificados. Lo que cambia es cuál de ellos recibe un fallo concreto, y cambia de forma gradual, proveedor a proveedor. Si ramificas tu lógica según code, este es un buen momento para trasladarla a retryable y reason, que describen el fallo directamente y no se ven afectados por la reclasificación.