错误、限流与重试

错误信封、稳定的 reason、限流与幂等重试。

更新于 10月28日

下面的错误信封和标为实测的 reason 都来自验收时的实测。每个已开放操作的状态码以 API 参考为准。

错误信封

公开 API 与 MCP 的 HTTP 错误共用一个 JSON 信封。下面是超出已授 scope 时真实返回的 403:

{
  "statusCode": 403,
  "code": "forbidden",
  "reason": "external.scope.denied",
  "message": "external.scope.denied",
  "requestId": "fa027664-2221-4273-858b-a28e317431a0"
}

按 reason 分支;联系支持时附上 requestId。不要解析 message。401 还会带 WWW-Authenticate: Bearer。OAuth 端点返回标准的 {"error": "…"}。MCP 工具失败以 isError 结果返回,文本是 reason。日志里记 reason 和请求 id,不记令牌、原始材料或学生姓名。

reason 一览

验收实测出现过的:

reason 状态码 含义与下一步
external.token.invalid 401 令牌缺失、过期或已撤销,或同时带了 Cookie。重新授权
external.audience.denied 403 令牌是为另一个资源签发的。按需换用 public-api 或 mcp 令牌
external.workspace.denied 403 X-Workspace-Id 与授权不符。去掉该头,或为那个工作区另行授权
external.scope.denied 403 未授该 scope。请教师重新授权
external.school.disabled 403 学校关闭了外部客户端。须由学校开放
external.disabled 404 本服务尚未开放 API
public.not_found 404 对象不存在,或本授权看不到
public.ingestion.file_unavailable 409 要解析的文件还没就绪或已经用过。换一份新上传的文件
authorization_pending、slow_down 400 设备轮询:继续等,或间隔加 5 秒
access_denied、invalid_grant 400 OAuth:被拒绝、学校已关闭,或授权码与 refresh 令牌已失效。停止

契约里定义、但验收没有触发的:external.rate_limited 与 public.quota.exhausted(429);public.idempotency.required、public.idempotency.invalid 与 public.request.invalid(400);public.idempotency.conflict、public.idempotency.expired、public.revision.stale、public.grade.preview_expired 与 public.file.not_uploaded(409);external.unavailable 与 public.unavailable(503)。

限流

公开 API 读取默认按授权(每分钟 60 次)、按教师(每分钟 120 次)和按工作区(每分钟 600 次)限流。超限返回 429 external.rate_limited,Retry-After 给出秒数;至少等这么久,不要并发重试。OAuth 端点按 IP、client 与凭据限流。授权用的密码重新验证按账号限次。验收没有触到这些上限;上面的数值来自默认配置,不是实测的 429。

幂等与重试

改变状态的写操作要带 Idempotency-Key 头,值为 UUID;MCP 写工具改用 idempotencyKey 参数。预览不需要。同一个键配同一个请求,返回原回执,不会执行第二次;同一个键配不同请求,返回 409 冲突。写请求超时或断线后,先用原来的键重试;换新键可能重复产生副作用。预览或场次版本过期时,重新读取并预览,再请教师确认当前的改动。重试不会让无权访问的对象变得可见。实际扣费与最终结果以服务端账本和任务回执为准。

继续阅读

错误、限流与重试 · 开发者文档