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

# 错误

> 统一的错误结构，以及每个状态码在这里的确切含义。

任何失败都返回一个带 `detail` 字段的 JSON，HTTP 状态码说明这是哪一类失败。

```json theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
{ "detail": "Insufficient quota: requested 8 GPUs, 2 available" }
```

绝大多数情况下 `detail` 是字符串。请求体校验是例外：FastAPI 返回数组，每个被拒的字段一条。

```json theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
{
  "detail": [
    {
      "loc": ["body", "spec", "resources", "pools"],
      "msg": "List should have at least 1 item after validation",
      "type": "too_short"
    }
  ]
}
```

要渲染错误的客户端两种都得处理。`loc` 是出问题字段的路径，用点连接起来即可；`msg` 是值得展示给人看的那句。

## 状态码

| 状态码   | 在这里的含义                                               | 该怎么办                                                          |
| ----- | ---------------------------------------------------- | ------------------------------------------------------------- |
| `400` | 请求读懂了，但被拒绝。最常见的一类：JobSpec 不合法、引用写错、取值超出声明范围          | 看 `detail`，它会点名具体是哪一项                                         |
| `401` | 没带 token、格式不对，或者已过期                                  | [重新认证](/zh-Hans/api-reference/authentication)。不要拿同一个 token 重试 |
| `403` | 认证通过，但没有权限。管理员专属接口、读不了的数据集、不属于你的部署                   | 重试没用，找管理员                                                     |
| `404` | 没有这个作业 / run / 数据集 / 模型 / 部署——或者有，但不允许你知道它存在         | 检查 id                                                         |
| `409` | 状态冲突：推广一个尚未 ready 的 revision、推送已存在的数据集版本、停止一个已经停了的作业 | 重新读当前状态再决定                                                    |
| `411` | 需要 `Content-Length` 的上传没带这个头                         | 补上                                                            |
| `413` | 上传体超过部署上限，或提交的归档解压后超限                                | 缩小打包内容，上限由 `FORGE_MAX_UPLOAD_MB` 决定                           |
| `422` | 请求体没通过 schema 校验                                     | 按 `detail[].loc` 点到的字段改                                       |
| `429` | 被限流——登录尝试或设备码轮询                                      | 退避。设备流轮询不要快于每 5 秒一次                                           |
| `500` | 控制平面的缺陷                                              | 可以重试一次；仍然失败就带上响应和时间戳报缺陷                                       |
| `501` | 这套部署没有开启该功能                                          | 需要管理员开启                                                       |
| `502` | 控制平面依赖的后端挂了：执行器、对象存储、OIDC 提供方                        | 通常是瞬时的，退避后重试                                                  |
| `503` | 控制平面活着，但有意不提供服务：维护模式，或升级前的排空                         | 稍后重试。`GET /api/version` 仍然会响应                                 |

## 读懂一次被拒的提交

`POST /api/jobs` 在任何调度动作之前就会拒绝，`detail` 会点名是哪道闸拦下的。下面这几种值得认识：

<AccordionGroup>
  <Accordion title="Recipe 握手失败" icon="git-compare-arrows">
    提交里的 `recipe.lock.json` 和服务端 catalog 对不上——名字、版本、digest 或 `framework.runtime_id`
    有差异。通常是平台发布了新的 recipe 版本，而你的实验还锁在旧版本上。

    `sf recipe status <exp>` 看差异，`sf recipe upgrade <exp>` 应用它。
  </Accordion>

  <Accordion title="配额不足" icon="cpu">
    申请的 GPU 数超过了账号能同时占用的上限。**在队列里排队不是这个错误**——排队的作业是已经被准入的。
    这是在门口就被拒绝，只有管理员能改。
  </Accordion>

  <Accordion title="镜像仓库不在允许列表里" icon="container">
    `--image` 指向的仓库主机不在部署允许的范围内。允许列表放在服务端是有意的：它是阻止提交去任意地方
    拉代码执行的那道闸。
  </Accordion>

  <Accordion title="拒绝覆盖 entrypoint" icon="terminal">
    `spec.source.entrypoint` 非空。entrypoint 归 recipe 所有，作业不能替换它。
    确实要跑自己的命令，用 `custom/custom` recipe。
  </Accordion>

  <Accordion title="打包里有敏感文件" icon="shield">
    打包器发现了 `.env`、`*.pem`、`id_rsa*` 之类，拒绝生成归档——这一步在你本机就失败了，请求根本没发出去。
    密钥通过平台的注入通道进入作业，不走工作目录。
  </Accordion>
</AccordionGroup>

<Note>
  一部分老代码路径抛出的错误文案目前仍是中文，正在随着相关代码被修改而逐步改成英文。
  遇到这种情况，报缺陷时引用状态码和接口路径更可靠。
</Note>
