跳到主要内容

错误

任何 2xx 之外的响应都带一个 JSON 体。请根据 code 分支,绝不要根据 message——消息是写给人看的,随时可能改措辞。

外层结构​

{
"detail": {
"code": "INSUFFICIENT_BALANCE",
"message": "Deploying needs about 1h of credit up front",
"balance_micro": 1500000,
"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
401bearer 令牌缺失、无效、过期、已吊销,或者把 API 密钥用在了账户端点上
402组织的余额不足以支付这次操作,或者付款已被冻结
403你通过了认证但没有权限:仅限管理员的操作、组织不对,或者对象不可修改
404不存在,或者你的组织看不到——这两者是故意做成无法区分的
409状态冲突:报价被人抢走、实例处在错误的状态、名称已被占用
410已失效:邀请已被使用、已过期或已被撤销
413请求体超出了该接口接受的大小
422取值不对:字段超出范围、磁盘比机器还大、枚举值未知
429请求过多:等待 Retry-After
503暂时不可用:主机无法完成的一次启动,或者此刻无法运行的登录校验。稍等片刻再试

租用方真正会撞上的​

情形状态码代码该怎么办
部署或启动时,余额不够支付这个实例运行时组织一小时的消耗(它的 GPU 和磁盘,加上运行中、启动中或创建中实例的 GPU 和磁盘,以及已停止实例的磁盘)——余额为正是不够的402INSUFFICIENT_BALANCE由管理员在控制台里添加余额。响应体里带着 balance_micro 和 required_micro。API 密钥不能充值。
在你的列表调用和部署之间,或者在你的部署预留期间,报价被人租走了409OFFER_UNAVAILABLE从你筛出的列表里取下一份报价重试。不要用同一个 offer_id 重试。什么都没有被创建。
这台机器被安排下线的时间,比启动一个实例所需的时间还早409MACHINE_IN_MAINTENANCE响应体中带有 next_maintenance。换台机器部署,或等这段窗口过去。这不是容量问题——机器上还有空闲 GPU——所以窗口结束后用同一份报价重试是可以的。
disk_gb 不在 10–20000 之内422校验错误列表发一个落在范围内的值
disk_gb 比主机的磁盘还大422DISK_TOO_LARGE响应体里带着 max_disk_gb。按不超过它的值重试,或者换一台更大的机器。
仅限管理员的操作,或者用 API 密钥去做任何管理员操作403ADMIN_REQUIRED改用属于管理员的会话令牌。结账、邀请和成员管理永远不对密钥开放。见角色与权限。
吊销一个未知的、已经吊销的,或属于别的组织的密钥404API_KEY_NOT_FOUND重新调 GET /v1/api-keys 列一遍,用当前的 id
从一个不允许的状态去停止、启动或销毁409INVALID_STATE先读一下 status。消息里会点明当前那个状态,例如 Cannot start an instance while it is running。
在不支持虚拟机的机器上用 vm 模板422OFFER_NOT_VM_CAPABLE筛出 vm_capable 为 true 的报价
凭据不能附加的 ssh_key_id:不是你自己的,或者——用 team 密钥时——不是现任成员的404SSH_KEY_NOT_FOUND用会话令牌调 GET /v1/ssh-keys 列一遍,从中挑一个 id
组织里已经有 25 个未销毁的实例409INSTANCE_LIMIT_REACHED响应体里带着 limit。先销毁一个——已停止的和处于 error 的实例都算数,所以停止腾不出名额。
组织有一笔付款争议尚未结束402PAYMENTS_FROZEN在争议结束之前,部署和启动都会暂停。
模板尚未发布、锁定的 CUDA 比机器的旧,或需要非 x86_64 硬件422TEMPLATE_COMING_SOON、TEMPLATE_CUDA_TOO_NEW、TEMPLATE_ARCH_UNSUPPORTED部署之前,拿模板的 coming_soon 以及 constraints.cuda_max、constraints.arch 对照报价的 cuda_version 检查一遍。
另一个组织的、从私有镜像仓库拉取的模板,或者其机器不为控制平面所知的报价422、409TEMPLATE_REQUIRES_OWNER、OFFER_NOT_PINNABLE什么都没有被创建。用你自己的仓库凭据复制模板,或者重新列出报价。
启动一个主机接不了的实例409、503HOST_UNREACHABLE、START_REFUSED、START_UNAVAILABLE实例仍是 stopped。稍后重试——START_UNAVAILABLE 稍等片刻即可。消息说主机已经不再持有工作负载的 START_REFUSED 不会成功:销毁并重新部署。
启动一个 GPU 已被释放(gpus_released)的实例,而另一位租户正在使用其中一块409CAPACITY_UNAVAILABLE实例仍是 stopped,磁盘还在。稍后重试;启动必须取回同样的 GPU,所以换别的机器或报价都不行。
同一调用方的请求过多429RATE_LIMITED等待 Retry-After 响应头里的秒数(响应体里也有 retry_after_s),然后重试。
请求体超过大小上限413PAYLOAD_TOO_LARGE响应体里带着 limit_bytes。发送更少的内容:大多数接口为 1 MiB,模板为 4 MiB。
你的组织看不到的实例、报价或模板404INSTANCE_NOT_FOUND, OFFER_NOT_FOUND, TEMPLATE_NOT_FOUND检查你发的 X-Org-Id,以及那个对象是否还在

认证和组织相关的失败——TOKEN_INVALID、TOKEN_EXPIRED、NOT_A_MEMBER、ORG_MISMATCH、INVALID_ORG_ID——在身份认证里讲。完整的代码清单见错误代码。

重试​

响应要重试吗?
402不。在余额到账之前——如果是 PAYMENTS_FROZEN,则是在争议结束之前——什么都不会变。
409 INSTANCE_LIMIT_REACHED只有在销毁一个实例之后才行。
409 OFFER_UNAVAILABLE要,换一份报价。
409 MACHINE_IN_MAINTENANCE要,换一台机器;或者等过了 next_maintenance 再用同一台。
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,而那恰恰是你本来就不会被重复扣费的情况。