错误码
调用失败时,API 返回 HTTP 状态码和 JSON 信封,其中的 code 说明出了什么问题。以下是 API 可能返回的全部 25 个错误码。v1 内可能会新增错误码:遇到未知的错误码时,按其 HTTP 状态码处理。
错误信封
所有错误响应体都是这种结构;code 和 message 始终存在。
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| error | object | 是 | |
| error.code | string | 是 | Machine-readable error code. Each response lists the codes it can carry; new codes may be added within v1, so treat an unknown code by its HTTP status. |
| error.message | string | 是 | Human-readable explanation (English). |
| error.requestId | string | 否 | The X-Request-Id of this request — quote it when reporting a problem. Sent since v1.1. |
| error.detail | object | 否 | Structured context for the error, such as the offending field; omitted when there is none.
|
| error.docs | string | 否 | Where the error codes are explained. Sent since v1.1.
|
真实的错误响应——请求中缺少必需字段:
curl -sS 'https://ecdsa.com/api/v1/jwt/decode' \
-H 'content-type: application/json' \
-d '{}'{
"error": {
"code": "missing_field",
"message": "Field \"token\" is required and must be a non-empty string.",
"requestId": "docs-example",
"docs": "https://ecdsa.com/developers#errors"
}
}全部错误码
| 错误码 | HTTP | 含义 | 出现场景 | 处理方法 | SDK |
|---|---|---|---|---|---|
| invalid_json | 400 | The body is not valid JSON or not a JSON object; or the input nests arrays and objects more than 64 levels deep (JSON documents inside string fields count too), or is too complex to inspect for private keys. | 典型原因:请求体是表单编码或纯文本而不是 JSON,顶层是 JSON 数组或字符串,或者程序生成的输入嵌套过深。content-type 请求头无关紧要,关键在于请求体本身。 操作: Verify an ECDSA signature, Convert a signature between DER and raw r‖s, Decode a JWT (no signature check), Verify an ES256/ES384/ES512 JWT signature, Decode an X.509 certificate or chain, TLS signature-health grade for a domain, Create a webhook endpoint, Delete a webhook endpoint, Send a test event | 以单个 JSON 对象作为请求体发送。如果输入是程序生成的,检查其嵌套深度。 | 不重试 |
| missing_field | 400 | A required field is absent or empty. | 操作要求的字段缺失、为 null、为空或不是字符串——常见原因是字段名拼写不同,例如把 publicKey 写成了 public_key。 操作: Verify an ECDSA signature, Convert a signature between DER and raw r‖s, Decode a JWT (no signature check), Verify an ES256/ES384/ES512 JWT signature, Decode an X.509 certificate or chain, Create a webhook endpoint, Delete a webhook endpoint, Send a test event | 补上错误消息中指出的字段;该操作的参考页面列出了所有必需字段。 | 不重试 |
| invalid_input | 400 | A field could not be parsed — the message explains exactly why. | 字段存在但无法解析:密钥、签名、令牌或证书使用了该操作无法识别的编码或格式。 操作: Verify an ECDSA signature, Convert a signature between DER and raw r‖s, Decode a JWT (no signature check), Verify an ES256/ES384/ES512 JWT signature, Decode an X.509 certificate or chain, Create a webhook endpoint | 查看错误消息——其中会指出字段和原因。检查编码(十六进制、base64、PEM);如果是签名,还要检查曲线。 | 不重试 |
| private_key_rejected | 400 | The request contains private-key material (a PEM PRIVATE KEY block, an OpenSSH, SSH2 or PuTTY private key, or a JWK with "d"). Never send private keys anywhere. | 在只需要公钥部分的地方粘贴了完整的密钥文件:PKCS#8 或 SEC1 PEM,OpenSSH 或 PuTTY 私钥,或者仍带有“d”的 JWK——嵌套在存放 JSON 的字符串中也算。 操作: Verify an ECDSA signature, Convert a signature between DER and raw r‖s, Decode a JWT (no signature check), Verify an ES256/ES384/ES512 JWT signature, Decode an X.509 certificate or chain, TLS signature-health grade for a domain, Create a webhook endpoint, Delete a webhook endpoint, Send a test event | 只发送公开数据。需要处理私钥时,使用浏览器工具——它们在你的机器上运行,不发送任何数据。 | 不重试 |
| unsupported_algorithm | 400 | The token's algorithm is not one this operation verifies. | JWT 使用了该操作不验证的算法:HS*、RS*、PS*、EdDSA、ES256K 或 none。 | 此 API 验证 ES256、ES384 和 ES512。使用其他算法的令牌请用 JWT 库在本地验证——切勿把 HMAC 密钥发送到任何地方。 | 不重试 |
| invalid_domain | 400 | Not a public DNS hostname (IP addresses, single-label names and paths are refused). | 路径段是 IP 地址、不含点的名称(例如 localhost),或者不是主机名的文本。名称前后的协议、端口或路径会先被去掉。 | 发送公网主机名,例如 github.com。IP 地址和内部名称无法从这里扫描。 | 不重试 |
| scan_dns_error | 400 | The domain does not resolve in public DNS. | 在公共 DNS 中解析该名称失败:域名不存在(拼写错误、注册已过期,或者是只有内部 DNS 才能解析的名称),没有 A 或 AAAA 记录,或者 DNS 故障。 | 检查拼写,并确认该名称有 A 或 AAAA 记录。 | 不重试 |
| scan_private_address | 400 | The domain resolves (at least partly) to a private or reserved address. | 该名称的某个地址——IPv4、IPv6 或嵌入在 IPv6 中的 IPv4——位于私有或保留地址段,例如内部网络或环回地址。公有地址与私有地址混合时,会整体被拒绝。 | 检测可以从公网访问的主机——内部主机无法从这里扫描。 | 不重试 |
| webhook_url_refused随 API 密钥推出 | 400 | The webhook URL cannot receive deliveries: it is not https on port 443, its host is not a public DNS name, or the name does not resolve or resolves (at least partly) to a private or reserved address. | 创建端点时使用了 http URL、443 以外的端口、IP 地址或内部名称,或者主机的 DNS 应答中包含私有或保留地址——即使多个地址中只有一个属于这种情况也会被拒绝。 | 使用默认端口、公网主机名的 https URL。错误消息会说明 URL 违反了哪条规则;如果是地址被拒绝,还会指出是哪个地址以及所属的地址段。 | 不重试 |
| unauthorized | 401 | The Authorization or X-API-Key header is malformed, the API key is not valid (wrong checksum, unknown, revoked or expired), or the operation needs a key. | 存在 操作: Verify an ECDSA signature, Convert a signature between DER and raw r‖s, Decode a JWT (no signature check), Verify an ES256/ES384/ES512 JWT signature, Decode an X.509 certificate or chain, TLS signature-health grade for a domain, List webhook endpoints, Create a webhook endpoint, Delete a webhook endpoint, Send a test event | 去掉该请求头以匿名调用,或者发送完整且有效的密钥。 | 不重试 |
| forbidden_scope随 API 密钥推出 | 403 | The API key is valid but lacks a scope this operation requires; the message names it. | 密钥创建时没有包含操作所需的范围,例如只有 api 范围的密钥调用了需要 scan 范围的域名健康检查操作。 操作: Verify an ECDSA signature, Convert a signature between DER and raw r‖s, Decode a JWT (no signature check), Verify an ES256/ES384/ES512 JWT signature, Decode an X.509 certificate or chain, TLS signature-health grade for a domain, List webhook endpoints, Create a webhook endpoint, Delete a webhook endpoint, Send a test event | 使用具有该范围的密钥调用。 | 不重试 |
| webhook_limit_reached随 API 密钥推出 | 403 | The account already has as many webhook endpoints as its plan allows. | 账号已有的端点数量达到套餐上限后又创建端点;免费版允许一个。 | 删除不再需要的端点;如果要修改现有端点的描述或事件,用相同的 URL 重新创建它即可。 | 不重试 |
| not_found | 404 | No operation exists at this path. |
任何操作都可能返回此错误码。 | 对照 API 参考检查路径;所有操作都位于 /api/v1 之下。 | 不重试 |
| webhook_not_found随 API 密钥推出 | 404 | The API key's account has no webhook endpoint with this id. | 端点 ID 不属于该密钥所在的账号:已被删除、输入有误,或者属于其他账号。 | 用 GET /api/v1/webhooks 列出账号的端点,并使用其中的 ID。 | 不重试 |
| method_not_allowed | 405 | The path exists but does not accept this HTTP method; see the Allow header. | 用 GET 调用 POST 操作——例如在浏览器地址栏中打开它——或者反过来。 任何操作都可能返回此错误码。 | 使用 Allow 响应头中列出的方法:接收 JSON 请求体的操作用 POST,其他操作用 GET。 | 不重试 |
| payload_too_large | 413 | The body exceeds 100 KB. | 请求体超过 100 KB,通常是因为把整个证书包或文件粘贴进了一个字段。 操作: Verify an ECDSA signature, Convert a signature between DER and raw r‖s, Decode a JWT (no signature check), Verify an ES256/ES384/ES512 JWT signature, Decode an X.509 certificate or chain, Create a webhook endpoint, Delete a webhook endpoint, Send a test event | 每次调用少发送一些数据——一条证书链、一个令牌。 | 不重试 |
| rate_limited | 429 | Too many requests — see Retry-After. | 当前时间窗口内请求过多:不带密钥时按 IP 计算,带密钥时按密钥计算。对域名的实际扫描还会消耗按主机计算和全局计算的额度。 操作: API self-description, Verify an ECDSA signature, Convert a signature between DER and raw r‖s, Decode a JWT (no signature check), Verify an ES256/ES384/ES512 JWT signature, Decode an X.509 certificate or chain, TLS signature-health grade for a domain, List webhook endpoints, Create a webhook endpoint, Delete a webhook endpoint, Send a test event | 等待 Retry-After 中给出的秒数后再重试,并在客户端缓存响应。 | 最多重试 2 次 |
| quota_exceeded随 API 密钥推出 | 429 | A daily or monthly quota of the API key's account is used up. X-Quota-Reset (and Retry-After) say when it starts over; retrying earlier cannot succeed. | 使用密钥的调用已用完账号的每日或每月配额单位,或者每日域名扫描次数;测试密钥有各自更小的配额。 操作: Verify an ECDSA signature, Convert a signature between DER and raw r‖s, Decode a JWT (no signature check), Verify an ES256/ES384/ES512 JWT signature, Decode an X.509 certificate or chain, TLS signature-health grade for a domain, List webhook endpoints, Create a webhook endpoint, Delete a webhook endpoint, Send a test event | 在 X-Quota-Reset 给出的时间之前不要重试:配额要到那时才会重置,不会更早。 | 不重试 |
| internal_error | 500 | Unexpected server error. | API 未预料到的故障。它会连同请求 ID 一起记录到日志中——但绝不会记录请求体。 任何操作都可能返回此错误码。 | 如果问题持续出现,请报告错误响应体中的 requestId。 | 不重试 |
| scan_unreachable | 502 | The domain refused or dropped the connection on port 443. | 名称可以解析,但从互联网无法成功建立到 443 端口的 TCP 连接:没有 HTTPS 服务器、防火墙拒绝或丢弃了连接,或者主机已宕机。 | 确认该主机在 443 端口上向公网提供 HTTPS 服务。 | 最多重试 2 次 |
| scan_tls_error | 502 | The TLS handshake failed or presented no usable certificate. | 443 端口的连接可以建立,但 TLS 握手以告警或协议不匹配告终,或者服务器没有发送扫描器能读取的证书。 | 检查服务器的 TLS 配置,例如查看域名健康报告。 | 最多重试 2 次 |
| service_unavailable随 API 密钥推出 | 503 | API keys cannot be verified right now (the key store is unreachable); retry shortly. | 无法访问密钥存储,因此无法验证请求中提供的密钥。携带密钥的调用绝不会被当作匿名调用处理。 操作: Verify an ECDSA signature, Convert a signature between DER and raw r‖s, Decode a JWT (no signature check), Verify an ES256/ES384/ES512 JWT signature, Decode an X.509 certificate or chain, TLS signature-health grade for a domain, List webhook endpoints, Create a webhook endpoint, Delete a webhook endpoint, Send a test event | 稍后重试——SDK 会自动这样做。 | 最多重试 2 次 |
| webhooks_unavailable随 API 密钥推出 | 503 | Webhooks are switched off on this server: it has no signing keys configured. | 服务器没有配置 Webhook 签名密钥,因此无法对投递签名;在配置密钥之前,所有 Webhook 操作都会返回此错误码。 操作: List webhook endpoints, Create a webhook endpoint, Delete a webhook endpoint, Send a test event | 请求本身无需修改:此服务器暂时关闭了 Webhook。请稍后再试。 | 最多重试 2 次 |
| scan_timeout | 504 | The scan did not finish in time. | 解析名称、建立连接或 TLS 握手的耗时超出了扫描器允许的时间——主机响应慢或负载过高,或者数据包被静默丢弃。 | 稍后重试;响应慢或负载过高的主机可能会超出时限。 | 最多重试 2 次 |
| timeout | 504 | The operation did not finish within its time budget. | 处理请求的时间超过了 10 秒的时限。在请求限制范围内的输入预计不会出现这种情况。 操作: API self-description, Verify an ECDSA signature, Convert a signature between DER and raw r‖s, Decode a JWT (no signature check), Verify an ES256/ES384/ES512 JWT signature, Decode an X.509 certificate or chain, List webhook endpoints, Create a webhook endpoint, Delete a webhook endpoint, Send a test event | 重试一次;如果相同的输入再次超时,请报告错误响应体中的 requestId。 | 最多重试 2 次 |
重试
官方 SDK 会重试 429(quota_exceeded 除外)、502、503 和 504——最多 2 次——等待时间以 Retry-After 的要求为准(最长 60 秒),没有该响应头时采用带完全抖动(full jitter)的指数退避。每个操作都是其输入的纯函数,因此重试总是安全的;你自己的客户端也可以遵循同样的规则。