> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bizyair.vip/llms.txt
> Use this file to discover all available pages before exploring further.

# 错误与重试

> HTTP 错误码、任务状态机、失败原因与重试策略

## HTTP 错误码

所有 API 错误响应使用统一格式：

```json theme={null}
{
  "code": 40001,
  "message": "错误描述",
  "status": false,
  "data": null
}
```

| HTTP | 业务码   | 含义             | 处理建议                          |
| ---- | ----- | -------------- | ----------------------------- |
| 200  | 20000 | 成功             | 正常处理                          |
| 400  | 40001 | 参数错误           | 检查请求体 / Header                |
| 401  | 40100 | 未授权（Key 无效或缺失） | 检查 `Authorization` 头          |
| 403  | 40300 | 权限不足           | 确认当前帐号能否调用该 `web_app_id`      |
| 404  | 40400 | 资源不存在          | 检查 `requestId` / `web_app_id` |
| 429  | 42900 | 超出并发配额         | 降低并发 / 升级套餐                   |
| 500  | 50000 | 服务内部错误         | 重试；持续失败请联系支持                  |
| 503  | 50300 | 服务不可用（维护中）     | 稍后重试                          |

<Warning>
  业务码与 HTTP 状态码可能**不一致**。确认任务是否成功时，请以响应体 `code == 20000` 且 `status == true` 为准。
</Warning>

## 任务状态机

任务从创建到终止的完整状态转换图：

<Frame>
  <img src="https://mintcdn.com/docs-bizyair-vip/ZAJUUIEfQse20S2V/images/%E4%B8%AD%E6%96%87%E7%89%88.png?fit=max&auto=format&n=ZAJUUIEfQse20S2V&q=85&s=9a2492975abb7350a3fdb6e602f4ce15" alt="中文版" width="1546" height="1628" data-path="images/中文版.png" />
</Frame>

| 状态          | 含义   | 是否产生费用     |
| ----------- | ---- | ---------- |
| `Queuing`   | 排队中  | 取消时不计费     |
| `Preparing` | 准备中  | 免费         |
| `Running`   | 运行中  | 中断时仍产生部分费用 |
| `Success`   | 成功完成 | 完成全部计费     |
| `Failed`    | 失败   | 完全退款       |
| `Canceled`  | 已取消  | 免费         |

## 常见失败原因

### 1. `web_app_id` 不存在或无权限

```json theme={null}
{"code": 40400, "message": "web_app_id not found", "status": false}
```

**排查**：确认 ID 正确，且该 AI 应用处于已发布、已授权状态。

### 2. `input_values` 字段缺失或类型错误

```json theme={null}
{"code": 40001, "message": "invalid input_values: 84:CLIPTextEncode.text is required"}
```

**排查**：对照 AI 应用页紫色 API 按钮中的 `input_values` 完整 Schema，逐字段校对。

### 3. 输入文件 URL 不可访问

```json theme={null}
{"code": 20000, "status": true, "data": {"outputs": [{"audit_status": 4, "error_type": "INPUT_ACCESS_DENIED"}]}}
```

**排查**：确保使用的 URL 为 `commit` 接口返回的 BizyAir URL，而非任意公网 URL。

### 4. 内容审核不通过

```json theme={null}
{"outputs": [{"audit_status": 3, "error_type": "NSFW"}]}
```

**排查**：提示词中含敏感词 / 输入图含敏感内容，调整后重试。

### 5. Credits 余额不足

```json theme={null}
{"code": 42901, "message": "insufficient credits", "status": false}
```

**排查**：先充值。调用 `/y/v1/wallet` 确认余额。

### 6. 并发超限

```json theme={null}
{"code": 42900, "message": "too many concurrent tasks", "status": false}
```

**排查**：降低并发数、使用队列控制，或联系商务升级套餐。

## 重试策略

### 建议重试的错误

以下错误属于瞬态错误，安全重试：

| 情形                         | 重试策略                        |
| -------------------------- | --------------------------- |
| HTTP 429（限流）               | 指数退避 + jitter（基座 2s，最多 5 次） |
| HTTP 500 / 502 / 503 / 504 | 指数退避 + jitter，最多 3 次        |
| 网络超时 / 连接重置                | 正常重试，最多 3 次                 |
| WebHook 回调回逐 200 OK 以外     | 平台自动重试                      |

### 不建议重试的错误

| 情形          | 处理                                    |
| ----------- | ------------------------------------- |
| HTTP 400    | 修改参数后才重新提交                            |
| HTTP 401    | 重新获取 / 更新 API Key                     |
| HTTP 403    | 检查帐号权限 / 应用发布状态                       |
| HTTP 404    | 检查 ID 是否拼写错误后重提                       |
| 任务 `Failed` | 先看 `error_type` / `error_msg`，修正后重新提交 |

### 幂等性与 `requestId`

<Note>
  **BizyAir 不自动对任务创建请求去重**。如果你在没收到 `requestId` 的情况下盲重试 `/create`，可能产生重复任务与重复计费。建议：

  * 发送前先在客户端生成业务层幂等销 key
  * 若相同幂等销 key 对应的上一次已获 `requestId`，优先用 `/detail` 查询而非重新 `/create`
</Note>

### 参考实现（Python）

```python theme={null}
import time, random, requests

def post_with_retry(url, headers, json_body, max_retries=3):
    for attempt in range(max_retries + 1):
        try:
            resp = requests.post(url, headers=headers, json=json_body, timeout=(10, 60))
            if resp.status_code == 200:
                return resp.json()
            if resp.status_code in (429, 500, 502, 503, 504) and attempt < max_retries:
                wait = min(2 ** attempt + random.random(), 30)
                time.sleep(wait); continue
            resp.raise_for_status()
        except (requests.ConnectionError, requests.Timeout):
            if attempt < max_retries:
                time.sleep(2 ** attempt); continue
            raise
    raise RuntimeError("exceeded retry budget")
```
