教程
hiapi /v1/tasks 任务卡住或超时:诊断流程与重试策略
你往 POST https://api.hiapi.ai/v1/tasks 提交了一个任务,拿到了 taskId,可 GET /v1/tasks/{taskId} 查上去,data.status 好几分钟还停在 queued 或 handling——看起来"卡住"了;又或者你的轮询循环跑到自己设的上限也没等到终态,于是报了超时。先别急着重投:hiapi 的任务是异步的,"还没结束"和"已经失败"是两回事,诊断清楚再动手才不会越修越糟。
如果你看到的是
data.status已经是fail、error.code是TASK_TIMEOUT,或者浏览器/代理抛出字面的 HTTP 504——那是另一类问题(任务真的跑失败了,或超时发生在你和 hiapi 之间的网络层),请看 HiAPI 任务超时与 504 错误排查。本文只讲任务迟迟没到终态的"卡住"场景。
问题现象
一个"卡住"的任务,查询回来大致长这样(HTTP 200,但任务还在非终态):
{
"data": {
"taskId": "…",
"status": "queued",
"output": null,
"error": null
}
}
关键特征:data.status 是 queued(排队)/ handling(处理中)/ archiving(归档中)之一,data.error 为 null,data.output 还没有内容。这说明任务是健康的,只是还没跑完。
hiapi 的任务终态只有两个:data.status 为 success 或 fail。只要还不是这两个,就代表任务没结束——"卡住"几乎都发生在这段非终态里。
两个容易混淆的"假卡住":
查询直接返回
404:{"code": 404, "data": null, "message": "task not found"}这不是卡住,是
taskId写错了、任务根本没创建成功,或任务记录已过期——核对你提交时拿到的data.taskId。提交时就被同步拒绝(根本没拿到
taskId),例如 model 写错:{"code": 400, "data": null, "error_code": "MODEL_UNAVAILABLE", "message": "model not available via /v1/tasks"}这类是请求本身的问题,不是任务卡住,改对再提交即可。
常见原因(按命中概率排序)
1. 队列积压(最常见)
当某个模型(图像模型、视频模型,或任何重算力模型)正被大量调用时,你的任务会在该模型的队列里等着被 worker 捡起。
- 信号:
data.status是queued,data.error为null,距提交时间不长。 - 修复:放慢轮询节奏,5–10 秒查一次就够,不要 100ms 空转。多数任务会在一两分钟内被捡起。
2. 重模型本就耗时
任务已经被捡起(handling/archiving),但这个模型跑完一次本来就慢——长视频、高分辨率、多参考图都会显著拉长耗时。
- 信号:
data.status在handling或archiving,持续数分钟但没有报错。 - 修复:给重任务更宽的轮询上限(按模型能力留足余量)。耗时长 ≠ 失败,别在它快出结果时自己掐断。
3. 轮询姿势不对(最容易被误判成"卡住")
很多"卡住"其实是客户端问题:轮询间隔太短把自己绕晕、没设上限、或上限太短过早放弃。
- 信号:服务端
data.status一直在正常推进,但你的循环提前抛了超时,或你根本没在读data.status。 - 修复:用固定间隔(建议 5 秒)+ 合理上限(常规任务约 10 分钟,重任务更长)。超时应由你的循环判定,而不是指望一个服务端的
timeout状态——hiapi 没有这个状态。
4. 回调端不可达
如果你提交任务时带了回调(callback),任务本身可能已经 success,只是结果送不到你那里,于是看起来"没动静"。
- 信号:主动查询
data.status已是success、data.output有内容,但你的回调端什么都没收到。 - 修复:回调地址必须公网可达、能收
POST、并在约 10 秒内返回2xx;否则就改用轮询。细节见 为什么 hiapi 任务回调没触发。
修复步骤
- 先查一次状态,别凭感觉重投:
GET /v1/tasks/{taskId},读data.status和data.error。 - 按状态分流:
queued/handling/archiving→ 还在跑,等 5–10 秒再查(原因 1 / 2)。success→ 任务成功,去data.output取结果;若你在等回调却没收到 → 原因 4。fail→ 读data.error.code与data.error.message;若是TASK_TIMEOUT→ 看 超时与 504 指南。404 task not found→taskId错了或没创建成功,回头核对提交响应里的data.taskId。
- output 有时效:
data.output里的下载 URL 带expireAt(约 7 天),拿到后尽快落盘 / 转存,别长期存热链。 - 确认不是鉴权 / 请求问题:先跑下面的最小验证示例,排除 key 与 model id 的问题。
- 真要重试,用退避:见下一节的重试策略,别在紧循环里重复重投同一个 body。
最小验证示例
用一个最小请求确认 key 和任务接口本身是通的。model 用裸 id(例:gpt-image-2):
curl -s -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"input": { "prompt": "a single red apple on a white background, studio lighting" }
}'
提交成功会拿到类似 {"data":{"taskId":"…","status":"queued"}} 的响应。拿 taskId 去轮询:
curl -s "https://api.hiapi.ai/v1/tasks/<taskId>" \
-H "Authorization: Bearer $HIAPI_API_KEY"
- 如果返回
401、body 是{"error":{"code":"permission_denied","type":"hiapi_error","request_id":"…"}}——问题在 key,不在任务。先看 API Key 无效错误排查。 - 如果提交被
400+"error_code":"MODEL_UNAVAILABLE"拒绝——是 model id 的问题。传裸 id,并对照 hiapi "模型不可用" 错误。
不会越修越糟的重试策略
- 指数退避:建议 5s → 15s → 45s。
- 封顶 3 次:第三次还失败就升级处理(换模型、降配置、或开工单),别无限循环。
- 每次重试都是新任务:一次
POST /v1/tasks就是一个新的taskId、可能产生新的计费。hiapi 没有对外承诺的"幂等重投"——别指望重投同一个 body 会复用旧任务。 - 撞到 429 时,放慢的是提交速率,不是轮询速率:见 如何修复 hiapi 限流(429)错误。
一个稳妥的 Python 轮询 + 退避示例:
import time, os, requests
BASE = "https://api.hiapi.ai/v1/tasks"
HEADERS = {"Authorization": f"Bearer {os.environ['HIAPI_API_KEY']}"}
def submit_and_wait(body, poll_interval=5, max_wait=600):
r = requests.post(BASE, json=body, headers=HEADERS, timeout=30)
r.raise_for_status()
task_id = r.json()["data"]["taskId"]
deadline = time.time() + max_wait
while time.time() < deadline:
time.sleep(poll_interval)
data = requests.get(f"{BASE}/{task_id}", headers=HEADERS, timeout=30).json()
status = (data.get("data") or {}).get("status")
if status == "success":
return data["data"]["output"]
if status == "fail":
raise RuntimeError(data["data"].get("error"))
# queued / handling / archiving → 继续等
raise TimeoutError(f"task {task_id} 在 {max_wait}s 内未到终态")
注意终态判定只认 success 和 fail;其余状态(queued / handling / archiving)一律继续等,超时由你的 max_wait 决定。
什么时候该升级处理
- 带退避重试 3 次,每次都是同一个
data.error.code→ 不是瞬时抖动,改输入或换模型。 - 任务长时间停在
queued且毫无进展 → 去 hiapi 控制台 看有没有平台通知,带上request_id开工单。 data.status已是success但回调一直不来 → 该端点别再依赖回调,改成轮询。
相关内链
- HiAPI 任务超时与 504 错误排查——任务真的
fail在TASK_TIMEOUT,或你看到字面 504 时看这篇。 - 为什么 hiapi 任务回调没触发——回调没来导致"假卡住"的专篇。
- API Key 无效错误排查|模型不可用错误|限流 429 错误
FAQ
Q:多久算"超时"?有没有统一的超时时长?
A:没有统一数字,取决于模型;重任务(长视频、高分辨率)更久。而且 hiapi 没有服务端的 timeout 状态——所谓超时通常是你的轮询循环到达了你自己设的上限。真正在服务端超时失败的任务会是 data.status:"fail" + error.code:"TASK_TIMEOUT",那种情况见 超时与 504 指南。
Q:任务 queued 了 30 秒,要不要取消重试?
A:不要。30 秒对任何非平凡模型都在正常范围内,至少等两分钟再考虑重试。
Q:能取消正在跑的任务吗? A:一般不支持取消;即便能取消,队列 / 算力槽通常也已占用。让它跑完、查结果更划算。
Q:同样的请求昨天能跑,今天却卡住? A:绝大多数是模型层的队列积压(原因 1)。换一个能力相近的模型,或等 5–10 分钟队列回落再试。
Q:每个任务都超时,是我账号的问题吗? A:先去 hiapi 控制台 看有没有账号级通知,再确认是不是被限流(见 429 指南)。若都正常、且只是某一个模型在失败,那多半是那个模型的队列或后端,不是你的账号。
Q:重试一个卡住 / 超时的任务会被重复计费吗?
A:每次 POST /v1/tasks 都是一个新的计费任务。没产出结果的失败任务通常不计产出费,但队列 / 算力槽可能已占用。在意成本就事后到用量页核对。