> For the complete documentation index, see [llms.txt](https://docs.goassay.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.goassay.ai/developers/zh/shang-jia-ni-de-api-ru-men/reject-reasons.md).

# 拒绝原因

识别各类签名拒绝原因，修复请求路径或验证器设置。

现成的 Worker 和中间件会在应用处理调用前拒绝无效签名。阅读验证器响应中的原因，找到失败的检查项。

## 调用方会看到什么

签名被拒绝时，会返回 HTTP `401`、`content-type: application/json`，以及类似下方的响应体：

```json
{"error":"invalid_assay_signature","reason":"BAD_SIGNATURE"}
```

这是发给直接 HTTP 调用方（通常为 Assay）的响应，不保证客户的 AI 应用会显示同样的响应体。如果只使用核心库而不使用中间件，你的代码必须将失败结果转换为 HTTP 响应。

## 签名拒绝原因

以下八种原因都使用上方的 `401` 响应。检查遇到首个失败就会停止，因此修复一项后，可能出现另一项。

| 原因                | 验证器为何拒绝请求                                                                                               | 解决方法                                                                                                            |
| ----------------- | ------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `MISSING`         | `Signature` 或 `Signature-Input` 缺失或为空、任一请求头缺少 `assay` 成员，或缺少签名覆盖的 `Content-Digest`。                     | 检查请求是否经由 Assay，且代理转发了这三个请求头。普通无签名调用本就应该失败。                                                                      |
| `MALFORMED`       | 请求头无法解析；签名值类型错误；算法、时间戳、随机数或密钥 ID 缺失或无效；签名组件列表或顺序错误；非空请求体缺少签名摘要；缺少调用 ID 或 authority；或请求目标无效，例如以 `//` 开头。 | 保留请求头和原始目标。要求 `alg="ed25519"`、整数时间以及非空随机数和密钥 ID。让 Assay 生成签名。向核心验证器传入原始请求，不要传入重建的 JSON 或已解码的 URL。               |
| `WRONG_TAG`       | 标签缺失或不是 `assay-request`。                                                                                | 使用 Assay 提供方请求签名。为其他用途生成的签名必须继续被拒绝。                                                                             |
| `DIGEST_MISMATCH` | SHA-256 请求体摘要与 `Content-Digest` 不符，或该请求头不含可用且匹配的 `sha-256` 值。                                           | 解析前验证原始请求体。禁用验证器之前的请求体转换。摘要请求头语法损坏时，也可能产生 `MALFORMED`。                                                          |
| `EXPIRED`         | `expires` 早于 `created`；签名窗口超过 300 秒；或按默认时钟容差，当前时间不在 `created - 60` 至 `expires + 60` 之间。                 | 同步服务器时钟，移除固定测试时钟，避免将签名请求积压在队列中。通过 Assay 发起新调用。                                                                  |
| `UNKNOWN_KEY`     | 没有可用的 Ed25519 公钥匹配 `keyid`。这也包括获取密钥失败，且缓存中没有匹配密钥的情况。                                                    | 使用默认公钥 URL `https://api.goassay.ai/.well-known/assay-request-keys.json`。检查出站 HTTPS、DNS 和防火墙规则。从实际运行配置中移除测试夹具密钥。 |
| `BAD_SIGNATURE`   | 所选密钥无法验证收到的请求上的签名。                                                                                      | 保留方法、主机、路径、查询参数、调用 ID 和签名摘要。如果代理重写 `Host`，请设置公开 authority。注册最终 URL，避免调用发生重定向。                                   |
| `REPLAYED`        | 随机数已被接受，且仍在重放存储中。                                                                                       | 停止代理重试发送同一签名。通过 Assay 发起新调用。独立夹具用例各用全新存储，但重放测试序列内应保留同一存储。                                                       |

密钥缓存一小时。找不到密钥时，最多每 60 秒触发一次重新获取。获取超时为 5 秒；失败后验证器暂停 5 秒再重试。请恢复连接并等待下一次获取，不要绕过检查。

## 其他故障

这些是适配器或基础设施错误，不属于上述八种签名原因。

| 调用方看到的内容                                                                                          | 原因                                                 | 解决方法                                        |
| ------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ------------------------------------------- |
| `413 {"error":"payload_too_large"}`                                                               | 超过 Worker 或中间件请求体上限。默认 5 MiB（5,242,880 字节），在验证前检查。 | 缩小请求体。中间件可配置上限；现成 Worker 使用固定上限。            |
| Express：`500`、`error: "assay_verify_misconfigured"`，消息为 `mount assayVerify() before body parsers` | 请求体流已经被读取或解析。                                      | 先挂载验证器。                                     |
| Express：`400 {"error":"invalid_json"}`                                                            | 签名通过，但 JSON 请求体无法解析。                               | 发送有效 JSON。这与签名验证是分开的。                       |
| Go 中间件：`400 {"error":"bad_request"}`                                                              | 读取请求体失败。                                           | 检查连接和请求体流。                                  |
| Go 中间件：`500 {"error":"assay_verify_failed"}`                                                      | 重放存储返回错误。                                          | 恢复共享存储；出错时不要处理请求。                           |
| 带 `NONCE_STORE` 的 Worker：`503 {"error":"replay_store_unavailable"}`                               | 共享随机数存储失败，或返回不可用响应。                                | 恢复 Durable Object 绑定和存储。不会调用源站。             |
| Node 或 Python：服务器 / 框架错误                                                                          | 自定义重放存储抛出异常。库不会将其转换为签名原因。                          | 恢复存储，并在验证失败时继续拒绝请求。确切的 HTTP 错误响应取决于框架的错误处理。 |

## 确认是否成功

1. 在网关或服务中修复失败的检查项。
2. 在 Assay 的 **Connect & test** 步骤中，输入有效工具参数并点击 **Run the test again**。
3. 确认签名调用通过，并检查身份认证警告。

| 警告                         | 含义                                              | 解决方法                        |
| -------------------------- | ----------------------------------------------- | --------------------------- |
| **Signature not enforced** | 在签名模式或 **Both** 下，端点接受了测试器的无签名探测请求。             | 用验证覆盖所调用的路由，并关闭所有绕过源站保护的路径。 |
| **API key not enforced**   | 在 API 密钥模式或 **Both** 下，端点接受了不带已保存密钥请求头的探测请求。    | 在端点强制检查密钥。                  |
| **No authentication**      | 在 **Neither** 下，正常调用返回成功 HTTP 状态。此模式不会另做身份认证探测。 | 选择并执行一种身份认证方式。              |

这些警告不会阻止 **Go live**。测试通过且没有警告是有用的依据，但探测无法运行时也不会产生警告。请自行检查受保护路由和源站访问。

## 延伸阅读

* [API 密钥还是签名](/developers/zh/shang-jia-ni-de-api-ru-men/api-key-or-signature.md)。
* 上架你的 API（可选）：[或者：发布你自己的 API](https://docs.goassay.ai/list-your-api/zh/publish-your-own-api)。

## 下一步

* [将你的 API 映射到工具契约](/developers/zh/shang-jia-ni-de-api-jin-jie/map-your-api.md)。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.goassay.ai/developers/zh/shang-jia-ni-de-api-ru-men/reject-reasons.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
