/
LinkHarbor API 的错误响应是什么结构、最重要的错误代码分别是什么意思,以及你的代码应该如何应对。
API 的每个错误响应都采用相同的格式。你的代码应依据 error 字段中的错误代码,而不是 message 中的文本:代码保持稳定,文本则可能变化,并会翻译成账户语言。
错误响应的结构
{
"error": "validation_failed",
"message": "Some of the information provided is invalid. Please check and try again.",
"details": [
{ "field": "title", "reason": "minLength", "message": "…" }
],
"request_id": "6b1f0c2e-…"
} - error
- 机器可读的代码,例如 not_found。大多数错误还会在 X-Error-Code 响应头中给出,但请以响应体中的字段为准。
- message
- 人类可读的描述,使用账户语言:使用 API 密钥时为工作区所有者的语言,使用已连接的应用时为连接该应用的人的语言。没有有效令牌时(例如令牌检查产生的 401),语言遵循 Accept-Language,否则为英文。Content-Language 响应头会注明所用的语言。
- details
- 只在有更多信息时出现。输入校验产生的 422 是一个列表,每个问题都有 field、reason 和 message;业务逻辑产生的 422 以及所有其他错误则是一个对象,例如包含 reason、retry_after_sec 或 issues 列表。超出大小时,它包含 field、reason 和 limit,413 request_too_large 则包含 max_bytes 和 max_kb。所以请检查 details 是否为列表。
- request_id
- 请求的 ID,也在 X-Request-Id 响应头中。联系支持团队时请附上它。
例外情况:429 rate_limited 响应用 retry_after_sec 字段代替 details;429 和 403 insufficient_scope 的响应体中没有 request_id。令牌检查产生的 401 和结构校验产生的 422 没有 X-Error-Code 响应头;结构校验时只有顶层的 message 会被翻译,details 中的文本保持英文。X-Request-Id 响应头则始终存在。
最重要的代码
| HTTP | error | 含义 | 怎么办 |
|---|---|---|---|
| 400 | invalid_json | 请求体不是有效的 JSON | 检查 JSON |
| 400 | bad_request | Content-Type 错误或请求格式不正确 | 设置 Content-Type: application/json |
| 401 | missing_bearer_token | Authorization 请求头中没有令牌 | 设置请求头 Authorization: Bearer … |
| 401 | invalid_token | 令牌已过期或无效,或密钥已删除 | 获取新令牌;如果没有用,检查密钥 |
| 401 | invalid_api_key | 换取令牌时密钥 ID 或密钥错误 | 检查凭据 |
| 402 | plan_limit_reached | 达到套餐上限,例如短链接数量 | 升级或删除条目 |
| 403 | insufficient_scope | 缺少权限范围,或端点未对 API 密钥开放 | 创建一个带正确权限范围的密钥 |
| 403 | forbidden | 没有执行此操作的权限 | 在控制台中完成 |
| 403 | feature_not_available | 套餐不包含此功能 | 检查套餐 |
| 403 | block_type_requires_plan | 该模块类型只在更高的套餐中提供 | 选择其他模块类型或升级 |
| 403 | template_locked | 当前套餐不能使用该高级模板 | 从 GET /v1/templates/available 中选择模板 |
| 403 | workspace_suspended, workspace_read_only, workspace_grace_expired | 工作区因未结清的付款被锁定或处于只读状态 | 在控制台中处理付款 |
| 404 | not_found | 资源不存在或不属于你的工作区 | 检查 ID |
| 409 | conflict | 与当前状态存在一般性冲突 | 重新加载状态,修改输入 |
| 409 | workspace_template_in_use | 工作区模板仍被页面使用;页面数量在 details.count 中 | 把这些页面切换到其他模板,然后再删除 |
| 409 | handle_taken, slug_taken | 用户名或短链接 Slug 已被占用 | 换一个值 |
| 409 | form_in_use, page_not_private, page_not_published, never_published | 与当前状态冲突:表单仍在某个页面上,页面不是私密的或未发布,从未发布过 | 修改状态后重试 |
| 409 | page_limit_reached, link_limit_reached, block_limit_reached, form_limit_reached, asset_limit_reached, asset_storage_limit_reached, workspace_template_limit_reached | 达到套餐的数量或存储空间上限 | 移除条目或升级 |
| 409 | draft_not_publishable | 草稿有问题;问题列表在 details.issues 中 | 修复问题后重新发布 |
| 413 | request_too_large | 请求体超过该端点允许的大小(64 KB、1 MB 或 2 MB);上限在 details.max_kb 中 | 每次请求发送更少的数据,参见速率限制 |
| 413 | payload_too_large | 上传的文件超过 10 MB | 减小文件 |
| 422 | validation_failed | 输入无效或有未知字段;详情在 details 中 | 按 details 的说明修正字段 |
| 422 | handle_reserved, target_url_invalid, target_url_scheme, target_url_host | 用户名被保留,或目标网址无效或不被允许 | 换一个值 |
| 422 | workspace_template_disabled | 所选的工作区模板已停用 | 在“域名与模板”中启用该模板,或选择其他模板 |
| 422 | template_css_external, template_section_invalid | 工作区模板:CSS 从外部服务器加载内容,或 {{#if}}/{{#unless}}/{{#each}} 片段的位置不正确 | 移除外部地址,或在同一个标签或同一段文本内闭合该区块 |
| 422 | custom_css_external | 自定义 CSS 从外部服务器加载内容 | 从 CSS 中移除外部地址 |
| 429 | rate_limited, api_key_locked | 请求过多,或密钥因失败尝试被锁定 | 按 Retry-After 或 details.retry_after_sec 给出的时间等待 |
| 500 | internal_error | 意外错误 | 稍后重试,并记下 request_id |
| 503 | service_unavailable | 服务暂时不可用 | 稍等片刻后重试 |
读取输入错误
出现 422 validation_failed 时,details 会分别列出每个问题:field 是字段路径(嵌套对象用斜杠分隔,例如 theme_config/button_style),reason 是被违反的规则,例如 required、minLength、maxLength、enum 或 additionalProperties。出现 additionalProperties 时,message 会说明哪些字段是未知的,原因通常是字段名拼写错误。
代码中的推荐处理方式
- 400、413 和 422:不要重试,而是修正请求
- 401 invalid_token:获取一次新令牌后重试
- 403:不要重试;检查权限范围、套餐或谁有权执行此操作
- 404:检查 ID;删除之后出现这个错误是正常的
- 409:重新加载状态,再判断这个操作是否仍然需要
- 429:按 Retry-After 给出的时间等待后重试,参见速率限制
- 500 和 503:以逐渐延长的间隔重试几次
你可能还想了解
没找到答案?
告诉我们你需要什么,我们的客服团队会亲自帮你。