错误
任何 2xx 之外的响应都带一个 JSON 体。请根据 code 分支,绝不要根据 message——消息是写给人看的,随时可能改措辞。
外层结构
{
"detail": {
"code": "INSUFFICIENT_BALANCE",
"message": "Deploying needs about 1h of credit up front for this and the organization's other instances",
"balance_micro": 0,
"required_micro": 2305000
}
}
| 键 | 类型 | 含义 |
|---|---|---|
detail.code | 字符串 | 稳定、全大写,可以放心用来分支 |
detail.message | 字符串 | 一行给人看的解释 |
| 额外的键 | 视情况而定 | 针对这次具体失败的上下文 |
有两类失败用的是另一种结构。框架抛出的请求校验错误会在 detail 下放一个列表,每个有问题的字段一条:
{"detail": [{"type": "greater_than_equal", "loc": ["body", "disk_gb"], "msg": "Input should be greater than or equal to 10"}]}
而意料之外的服务端故障会在那里放一个纯字符串,比如 {"detail": "Internal Server Error"}。如果你在写客户端库,这三种形态都要处理。
HTTP 状态码
| 状态码 | 含义 |
|---|---|
| 200 | 请求成功 |
| 201 | 创建出了某个东西——一个实例、一份模板副本、一个 API 密钥 |
| 204 | 成功但没有响应体:吊销密钥、删除 SSH 密钥 |
| 400 | 请求本身有毛病,比如 X-Org-Id 不是一个 id |
| 401 | bearer 令牌缺失、无效、过期、已吊销,或者把 API 密钥用在了账户端点上 |
| 402 | 组织的余额不够这次操作 |
| 403 | 你通过了认证但没有权限:仅限管理员的操作、组织不对,或者对象不可修改 |
| 404 | 不存在,或者你的组织看不到——这两者是故意做成无法区分的 |
| 409 | 状态冲突:报价被人抢走、实例处在错误的状态、名称已被占用、实例数已达上限 |
| 410 | 已失效:邀请已被使用、已过期或已撤销 |
| 413 | 请求体超过了端点接受的大小 |
| 422 | 取值不对:字段超出范围、磁盘比机器还大、枚举值未知 |
| 429 | 请求过于频繁:等 Retry-After 给出的秒数 |
| 503 | 暂时不可用:主机暂时无法完成的启动,或暂时无法进行的登录验证。稍后重试 |
租用方真正会撞上的
| 情形 | 状态码 | 代码 | 该怎么办 |
|---|---|---|---|
| 余额不够组织在这个实例运行后跑一小时(这个实例的 GPU 加磁盘,加上运行中、启动中或正在创建的实例的 GPU 加磁盘,以及已停止实例的磁盘)时部署或启动,余额为正也一样 | 402 | INSUFFICIENT_BALANCE | 由管理员在控制台里添加余额。响应体里带着 balance_micro 和 required_micro。API 密钥不能充值。 |
组织里尚未销毁的实例已有 25 个——stopped 和 error 的也算 | 409 | INSTANCE_LIMIT_REACHED | 响应体中带有 limit。先销毁不再需要的实例,包括处于 error 的,再部署。 |
| 在你的列表调用和部署之间,或者就在你的部署预留的那一刻,报价被人租走了 | 409 | OFFER_UNAVAILABLE | 从你筛出的列表里取下一份报价重试。不要用同一个 offer_id 重试。什么都没有被创建。 |
| 这台机器被安排下线的时间,比启动一个实例所需的时间还早 | 409 | MACHINE_IN_MAINTENANCE | 响应体中带有 next_maintenance。换台机器部署,或等这段窗口过去。这不是容量问题——机器上还有空闲 GPU——所以窗口结束后用同一份报价重试是可以的。 |
disk_gb 不在 10–20000 之内 | 422 | 校验错误列表 | 发一个落在范围内的值 |
disk_gb 比主机的磁盘还大 | 422 | DISK_TOO_LARGE | 响应体里带着 max_disk_gb。按不超过它的值重试,或者换一台更大的机器。 |
| 仅限管理员的操作,或者用 API 密钥去做任何管理员操作 | 403 | ADMIN_REQUIRED | 改用属于管理员的会话令牌。充值订单、发票信息、邀请和成员管理永远不对密钥开放。见角色与权限。 |
| 吊销一个未知的、已经吊销的,或属于别的组织的密钥 | 404 | API_KEY_NOT_FOUND | 重新调 GET /v1/api-keys 列一遍,用当前的 id |
| 从一个不允许的状态去停止、启动或销毁 | 409 | INVALID_STATE | 先读一下 status。消息里会点明当前那个状态,例如 Cannot start an instance while it is running。 |
在不支持虚拟机的机器上用 vm 模板 | 422 | OFFER_NOT_VM_CAPABLE | 筛出 vm_capable 为 true 的报价 |
| 模板被标记为即将推出(镜像还没有发布) | 422 | TEMPLATE_COMING_SOON | 换一个模板。GET /v1/templates 会列出这种模板,但它们无法部署。 |
模板固定了较旧的 CUDA 栈(cuda_max),而机器的 CUDA 版本更高 | 422 | TEMPLATE_CUDA_TOO_NEW | 换一台 cuda_version 不超过模板上限的机器,或换一个模板 |
| 模板声明了 x86_64 以外的架构 | 422 | TEMPLATE_ARCH_UNSUPPORTED | Superheat 的机器都是 x86_64。改用 x86_64 镜像的模板。 |
| 别的组织的模板,从带凭据的私有镜像仓库拉取 | 422 | TEMPLATE_REQUIRES_OWNER | 只有拥有它的组织能部署。把它复制到你的组织并填入你自己的仓库凭据(前提是你有权拉取那个镜像)。什么都没有被创建。 |
| 报价所在的机器没有在机群控制平面登记 | 409 | OFFER_NOT_PINNABLE | 列表不会显示这种报价,一般是拿着旧的 offer_id。重新列出报价另选一份。什么都没有被创建。 |
| 启动一个 GPU 被释放过的实例,而原来那几块正被别人使用,或者在那台机器上已停止服务 | 409 | CAPACITY_UNAVAILABLE | 实例仍然是 stopped,磁盘完好,但启动成功之前拿不到磁盘上的数据。稍后重试,这期间照样收存储费。一直不成功的话,唯一的出路是销毁实例后重新部署——销毁会把磁盘连同数据一起删除。 |
| 启动一个主机接不住的实例 | 409, 503 | HOST_UNREACHABLE, START_REFUSED, START_UNAVAILABLE | 实例仍然是 stopped。稍后重试——START_UNAVAILABLE 可以很快重试。消息说主机已不再持有工作负载的 START_REFUSED 不会成功:销毁后重新部署。 |
| 同一个调用方的请求太多 | 429 | RATE_LIMITED | 等 Retry-After 响应头里的秒数(响应体里也有 retry_after_s),再重试。 |
| 请求体超过大小上限 | 413 | PAYLOAD_TOO_LARGE | 响应体里带着 limit_bytes。发小一点:大多数端点 1 MiB,模板 4 MiB。 |
凭据不能附加的 ssh_key_id:不是你自己的,或者——用 team 密钥时——不是现任成员的 | 404 | SSH_KEY_NOT_FOUND | 用会话令牌调 GET /v1/ssh-keys 列一遍,从中挑一个 id |
| 你的组织看不到的实例、报价或模板 | 404 | INSTANCE_NOT_FOUND, OFFER_NOT_FOUND, TEMPLATE_NOT_FOUND | 检查你发的 X-Org-Id,以及那个对象是否还在 |
所有部署错误都在保留任何东西之前返回:被拒绝的部署不会留下实例。
认证和组织相关的失败——TOKEN_INVALID、TOKEN_EXPIRED、NOT_A_MEMBER、ORG_MISMATCH、INVALID_ORG_ID——在身份认证里讲。完整的代码清单见错误代码。
重试
| 响应 | 要重试吗? |
|---|---|
| 402 | 不。在余额到账之前,什么都不会变。 |
409 OFFER_UNAVAILABLE | 要,换一份报价。 |
409 MACHINE_IN_MAINTENANCE | 要,换一台机器;或者等过了 next_maintenance 再用同一台。 |
409 INSTANCE_LIMIT_REACHED | 只有在销毁了至少一个实例之后才行。 |
409 OFFER_NOT_PINNABLE | 要,换一份报价——同一份永远不会成功。 |
409 INVALID_STATE | 只有在重新读取实例、确认这次状态转换现在合法之后才行——allowed_actions 会告诉你哪些合法。 |
409 HOST_UNREACHABLE、START_REFUSED、CAPACITY_UNAVAILABLE | 过一会儿再试,并逐步拉长间隔。这期间实例一直是 stopped。 |
429 RATE_LIMITED | 要,等 Retry-After 秒之后。 |
| 503 | 要,稍等片刻之后。 |
| 422 | 不。先把请求改对。遇到 INVALID_CURSOR 时,去掉游标从头列出。 |
401 TOKEN_EXPIRED | 要,用新的会话令牌重试一次。shk_ 密钥不会过期,所以密钥上出现 401 就意味着它被吊销了。 |
POST /v1/instances 不接受幂等键,所以一旦超时,你就不知道这次租用到底成没成。**去查,而不是去重试:**调 GET /v1/instances,按你的 label 比对。
用同一个 offer_id 重试不安全。一份报价是一种规格,不是一个独占名额 —— 只要那台机器还有空余 GPU,同一份报价就会再被满足一次,你会拿到第二个实例、单独计费,而你本来只想部署一次。只有当那台机器的份额已经用光时它才会返回 409,而那恰恰是你本来就不会被重复扣费的情况。