Tutorial
HiAPI tarea devuelve TASK_FAILED: causas y cómo solucionarlo
Entiende la respuesta de estado final de una tarea, corrige cada tipo de causa y distingue los fallos reales de los 4xx y los tiempos de espera agotados.
Al enviar una tarea asíncrona a la API de tareas de HiAPI, un envío correcto devuelve HTTP 200 y un taskId. La tarea se ejecuta después en segundo plano y, cuando la consultas repetidamente, puede terminar en el estado final fail. En ese caso, la consulta devuelve aproximadamente lo siguiente; observa que la llamada HTTP en sí sigue siendo 200:
{
"code": 200,
"data": {
"taskId": "tk-hiapi-01M4RK...",
"model": "seedream-5.0-lite/image-to-image",
"status": "fail",
"error": { "code": "TASK_FAILED", "message": "task failed" },
"created": 1791827316,
"completed": 1791827352,
"storage": "temp"
},
"message": "success"
}
Esto es lo que comúnmente se conoce como «error TASK_FAILED»: la solicitud fue aceptada, la tarea se ejecutó y no tuvo éxito. No es un error HTTP 4xx ni un tiempo de espera agotado. Este artículo te enseña a interpretar esta respuesta y a corregir cada tipo de causa.
Primero, aclaremos: TASK_FAILED no es un código de estado HTTP
El punto más importante que debes entender:
- El código de estado HTTP de la llamada de consulta es
200, e incluso el cuerpo de la respuesta dice"message": "success"; esto solo indica que la llamada a la API fue exitosa, no que tu tarea lo haya sido. "status": "fail"(dentro dedata) es el criterio para determinar que la tarea falló. Para una tarea finalizada,data.statussolo será"success"o"fail"."TASK_FAILED"es el valor dedata.error.code, no del status. Algunos fallos incluyen un código más específico y un mensaje más útil (ver más abajo).
Por eso, consulta siempre GET /v1/tasks/{taskId} y usa data.status como base para las bifurcaciones; nunca juzgues el éxito o el fracaso solo por el código de estado HTTP.
Localizar la causa en los detalles de la tarea
Una vez obtenida la respuesta de estado final, lee los campos de data en este orden:
- Primero mira
data.status: solo si es"fail"se considera que la tarea falló. - Luego lee
data.error.code: es la categoría de error evaluable por máquina (comoTASK_FAILED,INVALID_REQUEST,CONTENT_POLICY_VIOLATION). - Por último lee
data.error.message: es la explicación para humanos y normalmente señala directamente la causa (por ejemplo, que una URL de entrada no se puede obtener).
error.code básicamente determina si este fallo «se puede resolver con un reintento»: el TASK_FAILED genérico (con message casi siempre "task failed") suele ser un problema transitorio y se puede reintentar; los que tienen un código explícito (como INVALID_REQUEST, CONTENT_POLICY_VIOLATION) son fallos deterministas, y reintentar sin cambiar la entrada dará el mismo resultado sin importar cuántas veces se intente.
Causas comunes del estado final fail
Ordenadas aproximadamente de mayor a menor frecuencia.
1. La URL de imagen/vídeo de entrada no es accesible o no es pública
Esta es la causa más común en tareas de imagen a imagen y de imagen/vídeo a vídeo. Si tu input hace referencia a una URL que la plataforma no puede obtener, la tarea se aceptará pero fallará durante la ejecución. Una respuesta real de estado final:
"error": {
"code": "INVALID_REQUEST",
"message": "The image URL could not be downloaded. Please provide a reachable public HTTP(S) URL and try again."
}
Aquí el message ya lo dice claramente. Otros modelos exponen la misma causa raíz como un TASK_FAILED / "task failed" genérico.
Solución: aloja la entrada en una URL HTTPS accesible públicamente y verifícala antes de enviar:
curl -I "https://your-host.example.com/input.png"
# Debe devolver 200 y un content-type de medio directo (image/* o video/*)
# No debe ser 401/403/404 ni una página HTML
Las URL prefirmadas caducadas, las direcciones localhost / de red interna y los enlaces que requieren iniciar sesión son las trampas más comunes. Estos son fallos deterministas: si no corriges la URL, reintentar solo hará que la tarea se ejecute en vano otra vez.
2. Fallo transitorio o fallo de generación en el origen
A veces una tarea con un formato completamente correcto falla con el error.code: "TASK_FAILED" genérico y message: "task failed", sin más detalles. Este tipo suele ser una fluctuación transitoria.
Solución: reintenta una o dos veces. Si falla repetidamente con la misma entrada, simplifica la entrada (acorta el prompt, elimina campos opcionales) y vuelve a ejecutarla para acotar el rango del desencadenante.
3. Contenido bloqueado por la política de seguridad
Si el prompt o la imagen de entrada incumplen la política de seguridad de contenido de la plataforma, la tarea terminará con un error determinista de tipo política, con data.error.code igual a CONTENT_POLICY_VIOLATION.
Solución: esto es un fallo permanente; reintentar no sirve. Ajusta el prompt y los materiales de entrada, elimina el contenido infractor y vuelve a enviar.
4. Un parámetro que el modelo rechaza solo en tiempo de ejecución
La gran mayoría de los parámetros ilegales se bloquean en el momento del envío con HTTP 400 (ni siquiera obtienes un taskId); consulta la sección siguiente. Ocasionalmente, una opción que por sí sola es válida pero que el modelo no admite en combinación se rechaza solo durante la ejecución de la tarea, lo que resulta en data.status: "fail". El error.message señalará qué opción es.
Solución: lee data.error.message y luego consulta en la página del modelo las entradas admitidas por ese modelo (por ejemplo, la página del modelo GPT Image 2), y elimina o corrige el campo que señala.
Cómo distinguir TASK_FAILED, 4xx y tiempo de espera agotado
Hay tres situaciones completamente diferentes que se describen de forma genérica como «falló», pero la solución es distinta:
| Lo que ves | Significado | Dónde corregirlo |
|---|---|---|
POST devuelve no 2xx (400/401/402/429) y sin taskId |
La solicitud fue rechazada; no se ejecutó ninguna tarea | Corrige la solicitud / la key / el saldo (ver enlaces abajo) |
POST devuelve 200 + taskId, y la consulta muestra data.status: "fail" |
TASK_FAILED: la tarea se ejecutó y falló | Lee data.error.message (este artículo) |
POST devuelve 200 + taskId, y la consulta supera tu límite de tiempo pero sigue en un estado no final (como handling) |
Tiempo de espera agotado, no es un fallo | Sigue consultando / aumenta el tiempo de espera / reintenta |
Si no obtuviste ningún taskId, entonces no es TASK_FAILED, sino un error de solicitud:
HTTP 400parámetro ilegal, ausente o no admitido → Corregir el error de parámetro 400 de HiAPIHTTP 401API key no válida → Error de API Key no válida- Saldo insuficiente (se rechaza en el momento de la creación, así que no hay tarea que pueda fallar) → Corregir el error 402 de saldo insuficiente de HiAPI
- ID de modelo desconocido o no disponible (
MODEL_UNAVAILABLE) → «El modelo no existe / no está disponible» - La tarea nunca alcanza el estado final → Tiempo de espera agotado de tareas de HiAPI y error 504
Los fallos de autenticación se rechazan en la capa de solicitud y devuelven HTTP 401 + {"error":{"code":"permission_denied","type":"hiapi_error","request_id":"..."}}; no se genera ninguna tarea, así que naturalmente no hay TASK_FAILED.
Lista de verificación para la solución
- Consulta la tarea; no confíes solo en el POST. El envío solo te dice que la tarea se encoló. Llama a
GET /v1/tasks/{taskId}y miradata.status. - Confirma que es un fallo real:
data.status == "fail"(el código HTTP sigue siendo200). - Lee
data.error.codeydata.error.message. El message es tu señal principal. - Si menciona la URL de entrada: cambia la URL por una accesible públicamente y verifícala con
curl -I(200 + content-type de medio directo). - Si el message es genérico (
"task failed"): trátalo como un problema transitorio y reintenta; si sigue fallando repetidamente, simplifica la entrada. - Si es un error determinista como
CONTENT_POLICY_VIOLATION: es un fallo permanente; no reintentes automáticamente, solo cambiar la entrada sirve. - Confirma que el ID de modelo está actualmente en
GET /v1/modelsy coincide exactamente con el que enviaste. Un ID desconocido fallará en el envío con400 MODEL_UNAVAILABLE, no con un fail de estado final. - ¿No hay ningún
taskId? Entonces no es TASK_FAILED; pasa a la guía de error de solicitud correspondiente de arriba.
Ejemplo mínimo de verificación
Antes de investigar una tarea concreta, confirma tu key y la conectividad con una solicitud limpia. Llama a la interfaz unificada de tareas POST https://api.hiapi.ai/v1/tasks, usando el ID de modelo desnudo (sin sufijo de endpoint):
# 1) Enviar: se espera HTTP 200 + un taskId
curl -s https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"gpt-image-2","input":{"prompt":"a red bicycle on a white background","aspect_ratio":"1:1"}}'
# -> {"code":200,"data":{"taskId":"tk-hiapi-..."},"message":"success"}
# 2) Consultar: sustituye por el taskId que obtuviste
curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-xxxxxxxx \
-H "Authorization: Bearer sk-YOUR_KEY"
# -> en ejecución data.status es "handling", luego cambia a "success" o "fail"
Si el paso 1 devuelve 200 y taskId, tu key y la interfaz funcionan correctamente, y cualquier fallo es un problema de una tarea individual, no de integración. Si el paso 1 devuelve 401, la key es incorrecta; gestiona la key en la consola de HiAPI. Nota: este ejemplo enviará una generación real y generará costes.
Sobre la facturación: no pagues repetidamente por tareas condenadas al fracaso
Para saber si las tareas fallidas se cobran y cómo funcionan la retención y el reembolso, consulta ¿Se cobran las solicitudes fallidas de HiAPI?. Dos puntos clave:
- No reintentes automáticamente sin criterio en fallos deterministas. En casos como
CONTENT_POLICY_VIOLATIONo URL inaccesible, cada reintento es una nueva tarea y puede facturarse. Cambia primero la entrada; no dejes que la lógica de reintentos gire en vacío quemando dinero. - Verifica la URL de entrada con
curl -Iantes de enviar. Una comprobación HEAD es gratuita, mientras que una tarea condenada al fracaso por un enlace roto puede costar dinero.
FAQ
¿TASK_FAILED es un código de estado HTTP?
No. La llamada HTTP devuelve 200. TASK_FAILED es el valor de data.error.code en la respuesta de estado final, y el data.status de esa respuesta es "fail".
data.status es "fail", pero estoy buscando "TASK_FAILED"; ¿qué debo mirar?
Cada uno va en su lugar. Para una tarea finalizada, data.status siempre es "success" o "fail"; "TASK_FAILED" es un data.error.code genérico, y las tareas fallidas también pueden traer un código más específico (como INVALID_REQUEST, CONTENT_POLICY_VIOLATION) y un message accionable.
¿Qué TASK_FAILED se pueden reintentar y cuáles no?
El "task failed" genérico (sin más detalles) suele ser un problema transitorio y se puede reintentar una o dos veces; los fallos deterministas con código explícito (URL rota → INVALID_REQUEST, contenido infractor → CONTENT_POLICY_VIOLATION, parámetro rechazado por el modelo) no se resuelven reintentando; hay que cambiar la entrada.
Mi tarea se queda en handling, ni falla ni tiene éxito.
Eso es un tiempo de espera agotado, no un fallo. Sigue consultando o aumenta el tiempo de espera del cliente; consulta Tiempo de espera agotado de tareas de HiAPI y error 504.
Obtuve 400 / 401 / 402, en lugar de taskId.
Eso significa que la solicitud fue rechazada; no se creó ninguna tarea, así que no hay ningún «fallo». Usa las guías enlazadas arriba para corregir la solicitud, la key o el saldo.
¿Se cobran las tareas fallidas? Consulta ¿Se cobran las solicitudes fallidas de HiAPI? para saber cómo se gestionan la retención y el reembolso en caso de fallo.
¿Cómo confirmo que la URL de entrada es defectuosa?
Lee data.error.message. Los problemas de URL suelen indicar que la imagen o el vídeo no se pueden descargar; verifica con curl -I que el enlace devuelve 200 y es un archivo multimedia directo.
Artículos relacionados
Ver todos los artículos →-
Tutorial
Cómo llamar a hailuo-2.3-fast/image-to-video a través de la API de HiAPI: práctica con curl y Python
La primera solicitud ejecutable del nivel rápido y de bajo coste de imagen a vídeo: del ID del modelo a la descarga del MP4
-
Tutorial
Cómo llamar a hailuo-2.3/text-to-video mediante la API de HiAPI: curl, Python y ejemplos de solicitud ejecutables
-
Tutorial
Uso de Kandinsky 6.0 Pro texto a video en HiAPI: tutorial con curl y Python
Demostración práctica centrada en la solicitud: construir la llamada de prompt a clip de video, enviar la solicitud, sondear el estado de finalización y descargar el resultado