参考
正文错误码
每个业务码的含义、该怎么处理,以及哪些错误值得重试。
调用出错时,响应会给你一个说明问题类型的数字(code),和一句给人看的说明(msg)。程序按数字分支,说明拿来展示或写日志。
响应外壳
{ "code": 40201, "msg": "Insufficient balance", "request_id": "req_…" }code是业务码。200表示成功,其他值都列在下面。- 失败时没有
data字段,只有少数素材库错误会多一个data.reason。 - HTTP 状态码也会正确设置(
40201对应 HTTP402)。两者选一个判断,不要混用——我们建议用更具体的code。 request_id同时出现在X-Request-Id响应头里。联系客服时请附上。
如果响应根本不是 JSON(比如中间网络返回的 HTML 或纯文本页面),就按 HTTP 状态码处理,并把响应体开头记进日志。
错误说明的语言
msg 和失败任务的 errorMessage 默认是英文。请求时带上 Accept-Language(en、ja、ko、de、fr、es、pt-BR、ru、it、pl 之一),或在控制台设置 API 错误语言,就能拿到对应语言;其他语言(包括中文)会退回英文。错误响应带有 Content-Language 头。错误码不会随语言变化——这也是永远不要解析 msg 的原因之一。
当模型给出了具体的失败原因(比如参考图读不出来),errorMessage 会把这个原因以英文原样转达,内部细节已去掉。
通用错误码
code | HTTP | 含义 | 要重试吗? |
|---|---|---|---|
200 | 200 / 202 | 成功 | — |
400 | 400 | 请求或 input 不合法;msg 会指出问题 | 不要,先修正 |
40003 | 400 | 上传的文件和上传票据对不上(大小、类型或内容) | 不要,重新申请票据再上传 |
40004 | 400 | 请求本身合法,但模型现在无法支持这组参数组合 | 不要,改掉 msg 里点名的参数 |
401 | 401 | 缺少密钥、密钥不认识或已吊销(详情) | 不要 |
403 | 403 | 没有权限(见权限) | 不要 |
404 | 404 | 不存在,或属于另一个密钥 | 不要 |
409 | 409 | 和当前状态冲突(何时重试) | 视情况 |
40901 | 409 | 报价过期或价格变了 | 重新报价 |
413 | 413 | 请求体太大 | 不要,改为上传素材,别内嵌 |
429 | 429 | 请求太多 | 要,等 Retry-After 之后 |
500 | 500 | 我们这边出了问题 | 要,退避后重试 |
503 | 503 | 某个支撑服务暂时不可用 | 要,等 Retry-After 之后 |
余额与上限
code | HTTP | 含义 | 怎么办 |
|---|---|---|---|
40201 | 402 | 积分不够冻结这个任务的金额 | 购买积分后再发 |
40202 | 402 | 达到了密钥的消费上限 | 在 API 控制台调高上限,或等它重置 |
权限
code | HTTP | 含义 | 怎么办 |
|---|---|---|---|
40301 | 403 | 这个密钥不能调用这个模型 | 把模型加进密钥的允许列表 |
40302 | 403 | 请求来源不在密钥的 IP 白名单里 | 加上这个地址,或去掉该限制 |
40303 | 403 | 所在地区不提供服务 | 无法绕过 |
40310 | 403 | 账户邮箱还没验证 | 打开注册邮件里的链接;验证后密钥立即可用 |
如果密钥有效却收到一个普通的 403,说明账户暂时不能使用 API,请带上 request_id 联系客服。
模型可用性
code | HTTP | 含义 | 要重试吗? |
|---|---|---|---|
50301 | 503 | 这个模型现在接不了任务 | 要,稍后再试,或换个模型 |
40004 | 400 | 模型正常,但不支持这组设置 | 不要,改设置 |
这两种情况都不会创建任务,也不会冻结积分。
任务失败码
任务被受理后又失败的,state 是 "failed",errorCode 是下列之一。这个列表是封闭的:遇到其他值,一律按 upstream_failed 处理。
errorCode | 含义 | 要重试吗? |
|---|---|---|
invalid_request | 模型不接受这些参数 | 不要,先修正 |
unsupported_combination | 暂不支持这组参数组合 | 不要,换个设置 |
content_rejected | 模型拒绝了这段内容 | 不要,改提示词或参考素材 |
invalid_asset | 参考文件读不出来或已失效 | 重新上传后新建任务 |
rate_limited | 生成服务正忙 | 要,退避后重试 |
upstream_unavailable | 生成服务暂时不可用 | 要,稍后重试 |
generation_failed | 跑完了但没有产出 | 看情况,同样的输入往往会同样失败 |
timeout | 任务超时 | 看情况,试试更短或更低分辨率的输出 |
upstream_failed | 其他情况 | 要,退避后重试 |
失败的任务会释放冻结的积分,不花钱(少数模型对内容拒绝也收费,会在模型页注明)。errorMessage 用文字说明原因;程序只按 errorCode 判断。
什么时候 409 值得重试
| 情形 | 要重试吗? |
|---|---|
带同一个 Idempotency-Key 的两个请求同时到达 | 要,稍等片刻用同一个键重发 |
这个 Idempotency-Key 已用于别的请求或别的密钥 | 不要 |
| 上传的文件或产物还在处理中 | 要,几秒后再试 |
对还没结束的任务调用 jobs/retry | 要,等它进入终态后再试 |
对已成功的任务调用 jobs/retry | 不要,直接新建任务 |
| 上传票据或上传文件已过期 | 不要,重新上传 |
怎么写重试
只重试第二次可能成功的错误;有 Retry-After 就按它等,没有就指数退避:
const RETRYABLE = new Set([429, 500, 503, 50301]);
async function call(path, init, attempts = 4) {
for (let i = 0; i < attempts; i++) {
const res = await fetch(`https://api.popnow.ai/api/v1${path}`, init);
if (!res.headers.get('content-type')?.includes('json')) {
throw new Error(`HTTP ${res.status}: ${(await res.text()).slice(0, 200)}`);
}
const body = await res.json();
if (body.code === 200) return body.data;
if (!RETRYABLE.has(body.code)) throw new Error(`${body.code} ${body.msg} (${body.request_id})`);
const wait = Number(res.headers.get('retry-after')) * 1000 || 2 ** i * 1000 + Math.random() * 500;
await new Promise((r) => setTimeout(r, wait));
}
throw new Error('out of retries');
}import random, time, requests
RETRYABLE = {429, 500, 503, 50301}
def call(method, path, attempts=4, **kwargs):
for i in range(attempts):
res = requests.request(method, f"https://api.popnow.ai/api/v1{path}", timeout=60, **kwargs)
try:
body = res.json()
except ValueError:
raise RuntimeError(f"HTTP {res.status_code}: {res.text[:200]}")
if body["code"] == 200:
return body["data"]
if body["code"] not in RETRYABLE:
raise RuntimeError(f'{body["code"]} {body["msg"]} ({body.get("request_id")})')
retry_after = res.headers.get("retry-after")
time.sleep(float(retry_after) if retry_after else 2**i + random.random() / 2)
raise RuntimeError("out of retries")重试 createTask 时,一定要带同一个 Idempotency-Key,这样一个其实已经成功的请求不会被执行、扣费两次。
排查
- 记下
request_id和code。 - 在 API 控制台的日志里,按任务 ID 或
request_id查到这个任务。 - 还是解决不了?请联系客服,附上
request_id、时间(UTC)和code。永远不要发送你的 API 密钥。

