Tutorial
Tarefa HiAPI retorna TASK_FAILED: causas e como corrigir
Entenda o retorno de tarefa em estado terminal, corrija cada tipo de causa e diferencie falhas reais de 4xx e timeouts.
Ao enviar uma tarefa assíncrona para a interface de tarefas da HiAPI, um envio bem-sucedido retorna HTTP 200 e um taskId. A tarefa então é executada em segundo plano; quando você a consulta por polling, ela pode terminar no estado terminal fail. Nesse caso, o polling retorna aproximadamente o seguinte — observe que a chamada HTTP em si continua sendo 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"
}
É isso que todos chamam de "erro TASK_FAILED": a requisição foi aceita, a tarefa foi executada e, no final, não teve sucesso. Isso não é um erro HTTP 4xx e também não é um timeout. Este artigo ensina a interpretar esse retorno e corrigir cada tipo de causa.
Primeiro, entenda: TASK_FAILED não é um status code HTTP
O ponto mais importante a entender:
- O status code HTTP da chamada de polling é
200, e o corpo da resposta até contém"message": "success"— isso apenas indica que a chamada à API teve sucesso, não que sua tarefa teve sucesso. "status": "fail"(dentro dedata) é o critério para determinar a falha da tarefa. Para uma tarefa concluída,data.statussó pode ser"success"ou"fail"."TASK_FAILED"é o valor dedata.error.code, não de status. Algumas falhas vêm com um code mais específico e uma message mais útil (veja abaixo).
Portanto, sempre faça polling em GET /v1/tasks/{taskId} e use data.status como base para ramificação; nunca julgue sucesso ou falha apenas pelo status code HTTP.
Localize a causa nos detalhes da tarefa
Após obter o retorno em estado terminal, leia os campos de data nesta ordem:
- Primeiro veja
data.status— só é falha de tarefa se for"fail". - Depois leia
data.error.code— é a categoria de erro determinável por máquina (comoTASK_FAILED,INVALID_REQUEST,CONTENT_POLICY_VIOLATION). - Por fim leia
data.error.message— é a descrição para humanos, geralmente apontando diretamente a causa (por exemplo, alguma URL de entrada não pôde ser baixada).
error.code basicamente determina se esta falha "pode ser resolvida com retry": o genérico TASK_FAILED (message geralmente "task failed") costuma ser um problema transitório e pode ser retentado; os com code explícito (como INVALID_REQUEST e CONTENT_POLICY_VIOLATION) são falhas determinísticas — não importa quantas vezes você retente sem alterar a entrada, o resultado será o mesmo.
Causas comuns de fail em estado terminal
Aproximadamente em ordem decrescente de frequência.
1. URL de imagem/vídeo de entrada inacessível ou não pública
Esta é a causa mais comum em tarefas de image-to-image e image/video-to-video. Se seu input referencia uma URL que a plataforma não consegue baixar, a tarefa é aceita mas falha durante a execução. Um retorno real em estado terminal:
"error": {
"code": "INVALID_REQUEST",
"message": "The image URL could not be downloaded. Please provide a reachable public HTTP(S) URL and try again."
}
Aqui a message já explica tudo claramente. Outros modelos expõem a mesma causa raiz como o genérico TASK_FAILED / "task failed".
Correção: hospede a entrada em uma URL HTTPS acessível publicamente e valide antes de enviar:
curl -I "https://your-host.example.com/input.png"
# Deve retornar 200 e content-type de mídia direta (image/* ou video/*)
# Não pode ser 401/403/404, nem uma página HTML
URLs pré-assinadas expiradas, endereços localhost / de rede interna e links que exigem login são as armadilhas mais comuns. Isso é uma falha determinística — se a URL não for corrigida, o retry só vai executar a tarefa em vão mais uma vez.
2. Falha transitória ou de geração no upstream
Às vezes uma tarefa com formato perfeitamente correto falha com o genérico error.code: "TASK_FAILED", message: "task failed", sem mais detalhes. Essas geralmente são oscilações transitórias.
Correção: tente novamente uma ou duas vezes. Se falhar repetidamente com a mesma entrada, simplifique a entrada (encurte o prompt, remova campos opcionais) e execute novamente para reduzir o escopo do gatilho.
3. Conteúdo bloqueado pela política de segurança
Se o prompt ou a imagem de entrada ferir a política de segurança de conteúdo da plataforma, a tarefa termina com um erro determinístico de política, com data.error.code igual a CONTENT_POLICY_VIOLATION.
Correção: esta é uma falha permanente; retry não adianta. Ajuste o prompt e os materiais de entrada, remova o conteúdo violador e envie novamente.
4. Um parâmetro que o modelo só rejeita em tempo de execução
A grande maioria dos parâmetros inválidos é barrada no envio com HTTP 400 (você nem chega a receber o taskId) — veja a próxima seção. Ocasionalmente, alguma opção que é válida isoladamente mas que o modelo não suporta em combinação só é rejeitada durante a execução, resultando em data.status: "fail". A error.message indica qual opção.
Correção: leia data.error.message e consulte a página do modelo para verificar as entradas suportadas por ele (por exemplo, a página do modelo GPT Image 2), removendo ou corrigindo o campo indicado.
Como diferenciar TASK_FAILED, 4xx e timeout
Há três situações completamente diferentes que costumam ser chamadas vagamente de "falhou", mas as correções são distintas:
| O que você vê | Significado | Onde corrigir |
|---|---|---|
POST retorna não-2xx (400/401/402/429) e sem taskId |
Requisição rejeitada; nenhuma tarefa chegou a rodar | Corrija a requisição / key / saldo (veja os links abaixo) |
POST retorna 200 + taskId, e o polling mostra data.status: "fail" |
TASK_FAILED — a tarefa rodou e falhou | Leia data.error.message (este artigo) |
POST retorna 200 + taskId, e o polling ultrapassa seu deadline permanecendo em estado não terminal (como handling) |
Timeout, não falha | Continue o polling / aumente o timeout / retente |
Se você nem recebeu um taskId, então não é TASK_FAILED, mas erro de requisição:
HTTP 400parâmetro inválido, ausente ou não suportado → Corrigir erro de parâmetro 400 da HiAPIHTTP 401API key inválida → Erro de API Key inválida- Saldo insuficiente (rejeitado na criação, então não há tarefa para falhar) → Corrigir erro 402 de saldo insuficiente da HiAPI
- Model id desconhecido ou não disponível (
MODEL_UNAVAILABLE) → "Modelo inexistente / indisponível" - Tarefa nunca chega ao estado terminal → Timeout de tarefa HiAPI e erro 504
Falhas de autenticação são rejeitadas na camada de requisição, retornando HTTP 401 + {"error":{"code":"permission_denied","type":"hiapi_error","request_id":"..."}}, sem criar tarefa; naturalmente, não há que se falar em TASK_FAILED.
Checklist de correção
- Faça polling da tarefa, não confie apenas no POST. O envio só informa que a tarefa entrou na fila. Chame
GET /v1/tasks/{taskId}e vejadata.status. - Confirme que é falha real:
data.status == "fail"(o código HTTP continua sendo200). - Leia
data.error.codeedata.error.message. A message é seu principal sinal. - Se mencionar URL de entrada: torne a URL acessível publicamente e valide com
curl -I(200 + content-type de mídia direta). - Se a message for genérica (
"task failed"): trate como problema transitório e retente; se continuar falhando repetidamente, simplifique a entrada. - Se for erro determinístico como
CONTENT_POLICY_VIOLATION: é falha permanente, não faça retry automático — só alterar a entrada resolve. - Confirme se o model id está atualmente em
GET /v1/modelse é exatamente igual ao que você enviou. Um id desconhecido falha no envio com400 MODEL_UNAVAILABLE, e não como fail em estado terminal. - Não recebeu
taskIdnenhum? Então não é TASK_FAILED — vá para o guia correspondente de erro de requisição acima.
Exemplo mínimo de verificação
Antes de investigar uma tarefa específica, faça uma requisição limpa para confirmar sua key e conectividade. Use a interface unificada de tarefas POST https://api.hiapi.ai/v1/tasks, com o model id em id puro (sem sufixo de endpoint):
# 1) Envio — espera-se HTTP 200 + um 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) Polling — substitua pelo taskId recebido
curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-xxxxxxxx \
-H "Authorization: Bearer sk-YOUR_KEY"
# -> em execução, data.status é "handling", depois muda para "success" ou "fail"
Se o passo 1 retornar 200 e taskId, sua key e a interface estão normais, e qualquer falha será problema de uma tarefa individual, não de integração. Se o passo 1 retornar 401, a key está incorreta — gerencie keys no Console HiAPI. Atenção: este exemplo envia uma geração real e gerará custos.
Sobre cobrança: não pague repetidamente por tarefas fadadas a falhar
Para saber se tarefas falhas são cobradas e como funcionam a pré-cobrança e o reembolso, veja Requisições falhas da HiAPI são cobradas?. Dois pontos principais:
- Não faça retry automático cego em falhas determinísticas.
CONTENT_POLICY_VIOLATION, URL inacessível e afins: cada retry é uma nova tarefa e pode ser cobrado. Altere a entrada primeiro; não deixe a lógica de retry girar em falso queimando dinheiro. - Valide a URL de entrada com
curl -Iantes de enviar. Uma verificação HEAD é gratuita, enquanto uma tarefa fadada a falhar por link quebrado pode ser cobrada.
FAQ
TASK_FAILED é um status code HTTP?
Não. A chamada HTTP retorna 200. TASK_FAILED é o valor de data.error.code no retorno em estado terminal, e o data.status desse retorno é "fail".
data.status é "fail", mas estou procurando "TASK_FAILED" — afinal, qual olhar?
Cada um no seu lugar. Para uma tarefa concluída, data.status é sempre "success" ou "fail"; "TASK_FAILED" é um data.error.code genérico, e tarefas falhas também podem trazer codes mais específicos (como INVALID_REQUEST e CONTENT_POLICY_VIOLATION) e messages acionáveis.
Quais TASK_FAILED podem ser retentados e quais não?
O genérico "task failed" (sem mais detalhes) costuma ser transitório e pode ser retentado uma ou duas vezes; falhas determinísticas com code explícito (URL quebrada → INVALID_REQUEST, violação de conteúdo → CONTENT_POLICY_VIOLATION, parâmetro rejeitado pelo modelo) não se resolvem com retry e exigem alteração da entrada.
Minha tarefa fica em handling eternamente, nem falha nem conclui.
Isso é timeout, não falha. Continue o polling ou aumente o timeout do cliente; veja Timeout de tarefa HiAPI e erro 504.
Recebi 400 / 401 / 402 em vez de taskId.
Isso é rejeição da requisição — nenhuma tarefa foi criada, então não há "falha". Use os guias linkados acima para corrigir a requisição, a key ou o saldo.
Tarefas falhas são cobradas? Veja Requisições falhas da HiAPI são cobradas? para entender como a pré-cobrança e o reembolso são tratados em caso de falha.
Como confirmar que a URL de entrada está quebrada?
Leia data.error.message. Problemas de URL geralmente indicam que a imagem ou o vídeo não pôde ser baixado; use curl -I para verificar se o link retorna 200 e é um arquivo de mídia direto.
Artigos relacionados
Ver todos os artigos →-
Tutorial
Como chamar hailuo-2.3-fast/image-to-video pela API HiAPI: curl e Python na prática
A primeira requisição executável do nível rápido e econômico de geração de vídeo a partir de imagem — do ID do modelo ao download do MP4
-
Tutorial
Como chamar hailuo-2.3/text-to-video pela API HiAPI: curl, Python e exemplos de requisição executáveis
-
Tutorial
Usar Kandinsky 6.0 Pro text-to-video na HiAPI: tutorial de curl e Python
Demonstração prática com foco na requisição: montar a chamada de prompt para clipe de vídeo, enviar a requisição, consultar o status de conclusão e baixar o resultado