HiAPI
Blog

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.

Oct 22, 2026
HiAPI tarea devuelve TASK_FAILED: causas y cómo solucionarlo

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 de data) es el criterio para determinar que la tarea falló. Para una tarea finalizada, data.status solo será "success" o "fail".
  • "TASK_FAILED" es el valor de data.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:

  1. Primero mira data.status: solo si es "fail" se considera que la tarea falló.
  2. Luego lee data.error.code: es la categoría de error evaluable por máquina (como TASK_FAILED, INVALID_REQUEST, CONTENT_POLICY_VIOLATION).
  3. 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:

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

  1. 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 mira data.status.
  2. Confirma que es un fallo real: data.status == "fail" (el código HTTP sigue siendo 200).
  3. Lee data.error.code y data.error.message. El message es tu señal principal.
  4. 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).
  5. Si el message es genérico ("task failed"): trátalo como un problema transitorio y reintenta; si sigue fallando repetidamente, simplifica la entrada.
  6. Si es un error determinista como CONTENT_POLICY_VIOLATION: es un fallo permanente; no reintentes automáticamente, solo cambiar la entrada sirve.
  7. Confirma que el ID de modelo está actualmente en GET /v1/models y coincide exactamente con el que enviaste. Un ID desconocido fallará en el envío con 400 MODEL_UNAVAILABLE, no con un fail de estado final.
  8. ¿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_VIOLATION o 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 -I antes 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 →

Empieza a crear con artefactos de IA persistentes

Consigue tu API key y llama a modelos de imagen, vídeo y audio a través de una única API basada en tasks.

Leer la documentación de la API