错误代码
当某个操作被拒绝时,原因会以一个简短的机器可读代码返回。控制台把其中大部分渲染成 toast 提示;API 则以 JSON 返回。
{
"detail": {
"code": "OFFER_UNAVAILABLE",
"message": "This offer is no longer available"
}
}
少数代码会在 code 和 message 之外附带额外字段——DISK_TOO_LARGE 会返回 max_disk_gb,MACHINE_DISK_EXHAUSTED 会返回 available_disk_gb,客户端据此可以直接把滑块收到上限以内并重试,不必再发一次请求。
这两个值不能互换,夹错了会无限循环。max_disk_gb 是机器的总磁盘容量;available_disk_gb 是扣掉同机其他租户以及 50 GB 主机预留之后剩下的。所以一台机器可以通过 DISK_TOO_LARGE 而仍然返回 MACHINE_DISK_EXHAUSTED——即使是一台空机器,因为那份预留永远不出售。拿到 available_disk_gb 时请按它来夹。
身份验证与组织范围
| 状态码 | 代码 | 成因 | 处理方式 |
|---|---|---|---|
| 401 | TOKEN_INVALID | 没有 Authorization 头、令牌格式错误、API 密钥未知或已吊销,或者把 API 密钥发到了账户级接口 | 发送有效的 bearer 令牌。/v1/me 和 /v1/ssh-keys 这类账户级接口需要已登录的会话,而不是 shk_ 密钥 |
| 401 | TOKEN_EXPIRED | 会话令牌已过期 | 重新登录。无人值守的脚本请改用 API 密钥 |
| 403 | NOT_A_MEMBER | X-Org-Id 指向了一个你不属于的组织 | 去掉该请求头以使用你的个人组织,或者请管理员发送邀请 |
| 403 | ORG_MISMATCH | X-Org-Id 与该 API 密钥所属的组织不一致 | 移除该请求头,或改用属于该组织的密钥 |
| 403 | ADMIN_REQUIRED | 以成员身份或使用 API 密钥执行了仅管理员可做的操作——付款、邀请、成员管理、团队 API 密钥 | 请管理员操作,或在已登录的管理员会话中重新执行 |
| 400 | INVALID_ORG_ID | X-Org-Id 不是合法的 id | 从 GET /v1/orgs 中复制 id |
部署
| 状态码 | 代码 | 成因 | 处理方式 |
|---|---|---|---|
| 402 | INSUFFICIENT_BALANCE | 部署或启动实例时,你的余额不足以覆盖这个实例一小时的费用 —— GPU 加磁盘。余额大于零是不够的 | 充值余额。只有管理员才能充值 |
| 409 | OFFER_UNAVAILABLE | 从你打开报价到你点击部署之间,该形态的最后一份空闲已被拿走 | 返回市场另选一份报价。卡片上的数字只是一个快照,真正决定的是部署本身 |
| 404 | OFFER_NOT_FOUND | 传给 GET /v1/offers/{id} 的 id 不存在,或该报价已从目录中撤下。针对未知报价的部署返回的则是 OFFER_UNAVAILABLE | 重新列出报价,使用当前有效的 id |
| 422 | DISK_TOO_LARGE | 请求的 disk_gb 超过了该机器的总容量。响应中包含 max_disk_gb | 请求不超过 max_disk_gb 的容量,或改选磁盘更大的机器 |
| 409 | MACHINE_IN_MAINTENANCE | 这台机器已被安排下线,时间太近,无法在上面启动实例。响应中包含 next_maintenance | 改选别的机器,或等这段维护窗口过去再来。更远的窗口不会阻止部署——它会显示在报价上 |
| 409 | MACHINE_DISK_EXHAUSTED | 该机器的磁盘已经许诺给其他租户了。一台机器同时承载多位租户,磁盘是按剩余量而不是总量出售的——所以这个错误可能紧跟在一个通过了 DISK_TOO_LARGE 的 disk_gb 之后。响应中包含 available_disk_gb 和 requested_disk_gb | 按不超过 available_disk_gb 重试,或改选别的机器。available_disk_gb 可能为 0 |
| 422 | OFFER_NOT_VM_CAPABLE | 一个 vm 启动模式的模板被投放到了无法运行虚拟机的机器上 | 把该模板部署到支持虚拟机的报价上,或改用其他启动模式的模板 |
| 404 | TEMPLATE_NOT_FOUND | 模板 id 不存在,或该模板已被删除 | 使用模板库中的模板,或使用别人给你的 hash_id |
| 404 | SSH_KEY_NOT_FOUND | 该 ssh_key_id 不属于你的密钥 | 用 GET /v1/ssh-keys 列出并使用你自己账户下的 id。密钥属于用户,不属于组织 |
实例操作
| 状态码 | 代码 | 成因 | 处理方式 |
|---|---|---|---|
| 404 | INSTANCE_NOT_FOUND | 该实例 id 在本次请求所限定的组织中不存在 | 检查 id,并确认你处在正确的组织中 |
| 409 | INVALID_STATE | 该操作在实例当前状态下不合法——例如停止一个正在停止的实例,或销毁一个正在创建的实例 | 等实例进入 running 或 stopped 后再重试。参见 实例状态 |
模板
| 状态码 | 代码 | 成因 | 处理方式 |
|---|---|---|---|
| 403 | TEMPLATE_IMMUTABLE | 你试图编辑或删除由 Superheat 精选维护的系统模板 | 先复制一份,再编辑你的副本 |
| 409 | TEMPLATE_NAME_TAKEN | 你所在组织中已有同名模板(不区分大小写) | 换一个名称 |
| 404 | TEMPLATE_NOT_FOUND | 该 id 或 hash_id 无法解析到你可见的模板 | 确认分享链接完整且是最新的——启动配置一变,hash_id 就会变 |
| 422 | INVALID_TAB | 模板列表接口的 tab 查询参数不属于模板库的任何一个标签页 | 使用受支持的 tab 取值 |
SSH 密钥
| 状态码 | 代码 | 成因 | 处理方式 |
|---|---|---|---|
| 422 | INVALID_SSH_KEY | 该值不是一行 OpenSSH 公钥、密钥内容不是有效的 base64,或者密钥类型不受支持 | 把 .pub 文件的全部内容粘贴成一行,以密钥类型开头。参见 受支持的密钥类型 |
| 409 | DUPLICATE_SSH_KEY | 你已经添加过指纹相同的密钥 | 直接用已有的那把密钥,或先删除旧条目 |
| 404 | SSH_KEY_NOT_FOUND | 该密钥 id 不是你的 | 密钥按用户隔离。别的成员的密钥你永远看不到 |
团队与邀请
| 状态码 | 代码 | 成因 | 处理方式 |
|---|---|---|---|
| 400 | PERSONAL_ORG | 你试图把别人邀请进个人组织 | 先创建一个真正的组织,再从那里发邀请 |
| 404 | INVITE_NOT_FOUND | 邀请令牌不正确,或该邀请已被撤回 | 请管理员重新发一个链接 |
| 410 | INVITE_USED | 该邀请已被接受 | 请对方重新发一个邀请链接 |
| 410 | INVITE_EXPIRED | 该邀请已过期 | 请对方重新发一个邀请链接 |
| 404 | MEMBER_NOT_FOUND | 该用户不是本组织的成员 | 刷新团队页面——对方可能已被移除 |
| 400 | LAST_ADMIN | 移除或降级该成员会让组织没有任何管理员 | 先把另一名成员提升为管理员 |
余额
| 状态码 | 代码 | 成因 | 处理方式 |
|---|---|---|---|
| 422 | INVALID_AMOUNT | 自定义充值金额缺失或超出可接受范围 | 选择 $10、$25 或 $100 的充值包,或填写 $5 到 $1,000 之间的自定义金额 |
| 403 | ADMIN_REQUIRED | 由成员或使用 API 密钥发起了付款 | 请组织管理员来充值 |
API 密钥
| 状态码 | 代码 | 成因 | 处理方式 |
|---|---|---|---|
| 404 | API_KEY_NOT_FOUND | 该密钥 id 在本组织中不存在 | 重新列出你的密钥并使用当前有效的 id |
| 403 | ADMIN_REQUIRED | API 密钥试图创建或吊销另一个 API 密钥,或成员试图管理团队级密钥 | 在已登录的会话中创建和吊销密钥 |
校验失败的请求
如果请求的正文或查询字符串不符合 schema,它会在到达上述任何检查之前就被拒绝。这类请求返回 422,detail 下是一组字段错误,而不是一个 code:
{
"detail": [
{
"type": "less_than_equal",
"loc": ["body", "disk_gb"],
"msg": "Input should be less than or equal to 20000"
}
]
}
loc 条目指出了出问题的字段。值得记住的边界是:disk_gb 介于 10 和 20,000 之间,label 最长 64 个字符,日志接口上的 tail 介于 1 和 1,000 之间。