HiAPI
博客

教程

HiAPI 任务返回 TASK_FAILED:成因与修复方法

读懂终态任务返回,逐一修复各类成因,并把真失败和 4xx、超时区分开。

2026年10月22日 6
HiAPI 任务返回 TASK_FAILED:成因与修复方法

向 HiAPI 任务接口提交异步任务时,提交成功会返回 HTTP 200 和一个 taskId。任务随后在后台执行,当你轮询它时,它可能以终态 fail 结束。此时轮询返回大致如下——注意 HTTP 调用本身仍是 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"
}

这就是大家常说的「TASK_FAILED 错误」:请求被接受、任务跑了、最后没成功。它不是 HTTP 4xx 错误,也不是超时。本文教你读懂这段返回,并逐一修复各类成因。

先搞清楚:TASK_FAILED 不是 HTTP 状态码

最需要理解的一点:

  • 轮询调用的 HTTP 状态码是 200,返回体里甚至写着 "message": "success"——这只表示 API 调用成功,不代表你的任务成功。
  • "status": "fail"(在 data 里)才是判断任务失败的依据。对一个已完成的任务,data.status 只会是 "success" 或 "fail"。
  • "TASK_FAILED" 是 data.error.code 的取值,而不是 status。有些失败会带更具体的 code 和更有用的 message(见下文)。

所以永远要轮询 GET /v1/tasks/{taskId},并以 data.status 作为分支依据,绝不要只看 HTTP 状态码判断成败。

从任务详情里定位成因

拿到终态返回后,按这个顺序读 data 字段:

  1. 先看 data.status——是 "fail" 才算任务失败。
  2. 再读 data.error.code——它是机器可判的错误类别(如 TASK_FAILED、INVALID_REQUEST、CONTENT_POLICY_VIOLATION)。
  3. 最后读 data.error.message——这是给人看的说明,通常直接点出成因(比如某个输入 URL 拉不到)。

error.code 基本决定了这次失败「能不能靠重试解决」:泛化的 TASK_FAILED(message 多为 "task failed")往往是瞬时问题,可以重试;带明确 code 的(如 INVALID_REQUEST、CONTENT_POLICY_VIOLATION)属于确定性失败,不改输入重试多少次都是同样结果。

常见的终态 fail 成因

大致按出现频率从高到低排列。

1. 输入图片 / 视频 URL 不可访问或非公网

这是图生图、图/视频生视频任务最常见的成因。如果你的 input 引用了平台拉取不到的 URL,任务会被接受但在执行时失败。一个真实的终态返回:

"error": {
  "code": "INVALID_REQUEST",
  "message": "The image URL could not be downloaded. Please provide a reachable public HTTP(S) URL and try again."
}

这里 message 已经说得很清楚。另一些模型会把同样的根因暴露成泛化的 TASK_FAILED / "task failed"。

修复: 把输入托管到公网可访问的 HTTPS URL,并在提交之前先验证:

curl -I "https://your-host.example.com/input.png"
# 必须返回 200 且是直链媒体 content-type(image/* 或 video/*)
# 不能是 401/403/404,也不能是一个 HTML 页面

过期的预签名 URL、localhost / 内网地址、需要登录才能打开的链接,是最常见的几种坑。这类属于确定性失败——URL 不修好,重试只会再白跑一次任务。

2. 瞬时或上游生成失败

有时一个格式完全正确的任务会以泛化的 error.code: "TASK_FAILED"、message: "task failed" 失败,且没有更多细节。这类多半是瞬时抖动。

修复: 重试一到两次。如果用同样的输入反复失败,就精简输入(缩短 prompt、去掉可选字段)再跑,缩小触发范围。

3. 内容被安全策略拦截

如果 prompt 或输入图命中平台的内容安全策略,任务会以确定性的策略类错误结束,data.error.code 为 CONTENT_POLICY_VIOLATION。

修复: 这属于永久失败,重试无效。调整 prompt 和输入素材、去掉违规内容后再提交。

4. 模型在运行时才拒绝的某个参数

绝大多数非法参数会在提交时就以 HTTP 400 拦下(你根本拿不到 taskId)——见下一节。偶尔某个本身合法、但组合起来模型不支持的选项,只有在任务执行时才被拒,落到 data.status: "fail"。error.message 会点出是哪个选项。

修复: 读 data.error.message,再去模型页核对该模型支持的输入(例如 GPT Image 2 模型页),删掉或改正它点名的字段。

怎么区分 TASK_FAILED、4xx 和超时

有三种完全不同的情况都会被笼统地说成「失败了」,但修法不同:

你看到的 含义 去哪修
POST 返回 非 2xx(400/401/402/429)且没有 taskId 请求被拒,根本没有任务跑起来 修请求 / key / 余额(见下方链接)
POST 返回 200 + taskId,轮询显示 data.status: "fail" TASK_FAILED——任务跑了并失败了 读 data.error.message(本文)
POST 返回 200 + taskId,轮询超过你的截止时间仍停在非终态(如 handling) 超时,不是失败 继续轮询 / 调大超时 / 重试

如果你压根没拿到 taskId,那就不是 TASK_FAILED,而是请求错误:

认证失败在请求层就被拒,返回是 HTTP 401 + {"error":{"code":"permission_denied","type":"hiapi_error","request_id":"..."}},不会产生任务,自然也谈不上 TASK_FAILED。

修复 checklist

  1. 轮询任务,别只信 POST。 提交只告诉你任务入队了。调 GET /v1/tasks/{taskId},看 data.status。
  2. 确认是真失败: data.status == "fail"(HTTP 码仍是 200)。
  3. 读 data.error.code 和 data.error.message。 message 是你的首要信号。
  4. 若提到输入 URL: 把 URL 改成公网可达,用 curl -I 验证(200 + 直链媒体 content-type)。
  5. 若 message 是泛化的("task failed"): 当作瞬时问题重试;仍反复失败就精简输入。
  6. 若是 CONTENT_POLICY_VIOLATION 这类确定性错误: 这是永久失败,别自动重试——改输入才有用。
  7. 确认模型 id 当前在 GET /v1/models 里有、且和你发的完全一致。未知 id 会在提交时以 400 MODEL_UNAVAILABLE 失败,而不是终态 fail。
  8. 完全没有 taskId? 那就不是 TASK_FAILED——跳到上面对应的请求错误指南。

最小验证示例

在排查某个具体任务之前,先用一次干净的请求确认你的 key 和连通性。打统一任务接口 POST https://api.hiapi.ai/v1/tasks,模型 id 用裸 id(不带 endpoint 后缀):

# 1)提交——预期 HTTP 200 + 一个 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)轮询——换上你拿到的 taskId
curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-xxxxxxxx \
  -H "Authorization: Bearer sk-YOUR_KEY"
# -> 运行中 data.status 是 "handling",随后变为 "success" 或 "fail"

如果第 1 步返回 200 和 taskId,说明你的 key 和接口都正常,任何失败都是单个任务的问题,而非接入问题。如果第 1 步返回 401,说明 key 不对——到 HiAPI 控制台 管理 key。注意:该示例会提交一次真实生成,会产生费用。

关于计费:别为注定失败的任务反复付费

失败任务是否扣费、以及预扣与退款怎么走,见 HiAPI 失败请求会扣费吗?。两个要点:

  • 确定性失败不要盲目自动重试。 CONTENT_POLICY_VIOLATION、URL 不可达这类,每次重试都是一个新任务、都可能计费。先改输入,别让重试逻辑空转烧钱。
  • 提交前先用 curl -I 验证输入 URL。 一次 HEAD 检查是免费的,而一个因坏链注定失败的任务可能要付费。

FAQ

TASK_FAILED 是 HTTP 状态码吗? 不是。HTTP 调用返回 200。TASK_FAILED 是终态返回里 data.error.code 的取值,而这条返回的 data.status 是 "fail"。

data.status 是 "fail",但我在找 "TASK_FAILED"——到底看哪个? 各看各的位置。对已完成的任务,data.status 永远是 "success" 或 "fail";"TASK_FAILED" 是一个泛化的 data.error.code,失败任务也可能带更具体的 code(如 INVALID_REQUEST、CONTENT_POLICY_VIOLATION)和可操作的 message。

哪些 TASK_FAILED 能重试,哪些不能? 泛化的 "task failed"(无更多细节)多为瞬时问题,可以重试一两次;带明确 code 的确定性失败(坏 URL → INVALID_REQUEST、内容违规 → CONTENT_POLICY_VIOLATION、模型拒绝的参数)重试无效,必须改输入。

我的任务一直停在 handling,既不失败也不成功。 那是超时,不是失败。继续轮询或调大客户端超时;见 HiAPI 任务超时与 504 错误。

我拿到的是 400 / 401 / 402,而不是 taskId。 那些是请求被拒——没有任务被创建,也就没有什么「失败」。用上面链接的指南去修请求、key 或余额。

失败的任务会扣费吗? 见 HiAPI 失败请求会扣费吗? 了解预扣与退款在失败时如何处理。

怎么确认是坏的输入 URL? 读 data.error.message。URL 问题通常会提示图片或视频无法下载;用 curl -I 验证链接返回 200 且是直链媒体文件。

立即开始构建持久 AI 产物

获取 API 密钥,通过一个基于任务(task)的 API 调用图像、视频和音频模型。

阅读 API 文档