---
url: /zh/reference/error-codes.md
description: 框架的错误码与 HTTP 状态，以及查询请求被拒时的代码。
---

# 错误码

框架应答请求时使用的每个代码，即 `application/problem+json` 正文与命令结果中的 `code`，由 [`FrameworkErrors`](https://github.com/Ahoo-Wang/Wow/blob/main/api/manifest/src/main/kotlin/me/ahoo/wow/manifest/FrameworkErrors.kt) 生成；说明取自源码，为英文。领域拒绝的代码由领域自己定义，以 422 应答，除非宿主为它配置了别的状态（`wow.http.errors.[<code>].status`）。请求带 `If-Match` 时，`wow.aggregate.version-mismatch` 以 412 应答。

## 框架错误码

| 代码 | 状态 | 含义 |
| --- | --- | --- |
| `wow.auth.unauthenticated` | 401 | The request carries no valid credentials. |
| `wow.auth.forbidden` | 403 | The caller may not send this command. |
| `wow.aggregate.forbidden` | 403 | The aggregate is outside the caller's scope. |
| `wow.command.malformed` | 400 | The command body cannot be read as the command type. |
| `wow.command.invalid` | 400 | The command failed validation; the problem lists the violations. |
| `wow.wait.invalid` | 400 | The wait is not a chain the runtime can follow; the command was not run. |
| `wow.command.unhandled` | 400 | The aggregate does not handle this command. |
| `wow.aggregate.not-found` | 404 | The aggregate does not exist. |
| `wow.aggregate.exists` | 409 | The aggregate already exists. |
| `wow.aggregate.version-mismatch` | 409 | The aggregate is not at the expected version (412 when the request carried If-Match). |
| `wow.command.request-id-reused` | 409 | The request id was used by another command. |
| `wow.command.contended` | 409 | Concurrent writers kept winning the version; retrying with the same request id is safe. |
| `wow.aggregate.deleted` | 410 | The aggregate is deleted; only RestoreAggregate applies. |
| `wow.command.busy` | 429 | The command was not taken: its aggregate has too many commands waiting, or the node too many in flight; retry later. |
| `wow.command.unknown` | 503 | Whether the command committed is unknown; retrying with the same request id is safe. |
| `wow.command.failed` | 500 | The command's handling failed with an unexpected error; it committed nothing, and a retry fails alike. |
| `wow.node.closing` | 503 | The node is shutting down; retry on another node. |
| `wow.node.standby` | 503 | The node is on standby until the cut-over: it serves reads only. |
| `wow.storage.unavailable` | 503 | A store could not be reached or did not answer in time; retry later, a command with the same request id. |
| `wow.schedule.not-due` | 503 | A scheduled command arrived too long before its due time on this node's clock; it is sent again later. |
| `wow.schedule.job-invalid` | 400 | The job command does not fit its job or instance: an unknown job, another scope, or an instance not enabled. |
| `wow.subscription.parked` | 500 | A subscription on the wait chain parked the aggregate; the wait cannot be reached until it resumes. |
| `wow.wait.timeout` | 504 | The wait ran out of time; the command may have committed. The problem carries the last stage reached. |
| `wow.query.malformed` | 400 | The query body cannot be read as a query. |
| `wow.query.invalid` | 400 | The query failed admission; the problem lists the violations, each with its code (UNKNOWN\_FIELD, ...). |
| `wow.query.failed` | 500 | The query backend failed to run the query. |
| `wow.query.not-found` | 404 | A single query matched no record: a query result, not a statement that an aggregate does not exist. |
| `wow.query.dataset-not-found` | 404 | No dataset of that name is served to the caller. |
| `wow.query.timeout` | 504 | The query ran longer than its budget allows; narrow it rather than run it again (decision D254 ③). |
| `wow.query.min-version-not-reached` | 409 | The state read asked for a version the aggregate has not reached within the wait; the problem carries its current version: retry later. |
| `wow.query.busy` | 429 | The query was not run: its store has as many queries running as it allows; retry later. |
| `wow.query.dataset-unavailable` | 409 | The dataset is served but cannot be queried now, for the reason the problem names (it needs revision). |
| `wow.call.command-forbidden` | 403 | The calling service may not call this command: its wow.http.services.\<service>.commands do not list it. |

## 查询请求的代码

被拒绝的查询请求（`wow.query.malformed` 或 `wow.query.invalid`）会列出它拒绝的每一处，各带下列一个代码与它所指的请求部分，由 [`QueryErrorCodes`](https://github.com/Ahoo-Wang/Wow/blob/main/api/query-api/src/main/kotlin/me/ahoo/wow/api/query/QueryErrorCodes.kt) 生成。代码只增不改，也不复用。

| 代码 | 分组 |
| --- | --- |
| `INVALID_JSON` | Reading and decoding the request body. |
| `BODY_NOT_OBJECT` | Reading and decoding the request body. |
| `EMPTY_BODY` | Reading and decoding the request body. |
| `UNKNOWN_PROPERTY` | Reading and decoding the request body. |
| `UNKNOWN_TYPE` | Reading and decoding the request body. |
| `UNKNOWN_VALUE` | Reading and decoding the request body. |
| `INVALID_VALUE` | Reading and decoding the request body. |
| `INVALID_REQUEST` | Reading and decoding the request body. |
| `CURSOR_SORT_DUPLICATE` | Reading and decoding the request body. |
| `CURSOR_SORT_TOO_MANY` | Reading and decoding the request body. |
| `INVALID_CURSOR` | Reading and decoding the request body. |
| `SIZE_OUT_OF_RANGE` | The entry budget and gates (errorCode IllegalArgument). |
| `FILTER_TOO_LARGE` | The entry budget and gates (errorCode IllegalArgument). |
| `EXPENSIVE_OPERATOR_DISABLED` | The entry budget and gates (errorCode IllegalArgument). |
| `COUNT_REQUIRES_FILTER` | The entry budget and gates (errorCode IllegalArgument). |
| `RESIDUAL_GROUPS_EXCEEDED` | The entry budget and gates (errorCode IllegalArgument). |
| `EXPLICIT_ENTRY_REQUIRED` | The entry budget and gates (errorCode IllegalArgument). |
| `REPLAY_TOO_LONG` | A state point read (GET …/{id}/state?version=|at=, …/state/trace). |
| `UNKNOWN_FIELD` | Admission against the query model. |
| `UNSUPPORTED_CAPABILITY` | Admission against the query model. |
| `ELEMENT_SCOPE_REQUIRED` | Admission against the query model. |
| `VALUE_MISMATCH` | Admission against the query model. |
| `NOT_COLLECTION` | Admission against the query model. |
| `NOT_SINGLE_STRING` | Admission against the query model. |
| `MODEL_SEARCH_UNSUPPORTED` | Admission against the query model. |
| `CURSOR_NOT_ALLOWED` | Admission against the query model. |
| `PROTECTED_AGGREGATION` | Admission against the query model. |
| `PROTECTED_COMPARISON` | Admission against the query model. |
| `MISSING_KEY_REQUIRES_STRING` | Admission against the query model. |
| `ANY_REQUIRES_SINGLE_VALUE` | Admission against the query model. |
| `INCOMPLETE_PROJECTION` | Admission against the query model. |
| `METRIC_FILTER_SEARCH` | Admission against the query model. |
| `METRIC_FILTER_ELEMENT_MATCH` | Admission against the query model. |
| `METRIC_FILTER_ARRAY_FIELD` | Admission against the query model. |
| `NOT_PROJECTABLE` | Admission against the query model. |
| `EVENT_PROJECTION_TYPE_REQUIRED` | Admission against the query model. |
| `TEMPORAL_REPRESENTATION_REQUIRED` | Admission against the query model. |
| `TEMPORAL_CONFIGURATION_CONFLICT` | Admission against the query model. |
| `PARALLEL_ARRAY_SORT` | Admission against the query model. |
| `ARRAY_EQUALITY` | Admission against the query model. |
| `FIRST_LAST_REQUIRES_SINGLE_VALUE` | Admission against the query model. |
| `FIRST_LAST_REQUIRES_ORDER_BY` | Admission against the query model. |
| `TEMPORAL_AGGREGATION_UNSUPPORTED` | Admission against the query model. |
| `SORT_TOO_MANY` | Admission against the query model. |
| `SORT_FIELD_DUPLICATE` | Admission against the query model. |
| `IDENTITY_UNDEFINED` | Admission against the query model. |
| `STORAGE_UNSUPPORTED` | Admission against the query model. |
| `PREVIOUS_UNSHIFTABLE` | Admission against the query model. |
