# Errors

> Error codes of versioned writes, simulations and reverts, with the HTTP status, the CLI exit code and what to do.

Errors come in the API's usual envelope, `{"error": {"code": "…", "message": "…"}}`, with any extra data at the same level as `error`. The MCP server and the SDKs return the same codes; the CLI prints a message in Spanish and exits with the code in the last column.

| HTTP | Code | When | What to do | CLI exit |
|---|---|---|---|---|
| 412 | `version_conflict` | The zone is no longer at the version you sent in `If-Match` (or `expected_version`): someone changed it after your simulation. The body has `current_version`. Nothing was applied. | Look at what changed (`zones diff`), simulate again and confirm the new plan. | 3 |
| 428 | `if_match_required` | A revert was sent without `If-Match`. | Send the zone's current version. | 1 |
| 422 | `reason_required` | No reason, an empty one, more than 500 characters or a line break in it. | Send `X-Change-Reason` (`--reason` in the CLI, `reason` in MCP and the SDKs). | 2 or 1 |
| 422 | `invalid` | The change or the configuration it produces is not valid, or the configuration of an edge node could not be built with it. `field` names the field when there is one. | Fix the value; the simulation fails the same way, so check with a dry run. | 1 |
| 409 | `missing_certs` | A revert would leave sites without a valid certificate. The body has `hostnames`. | Revert anyway with `allow_missing_certs` (`--allow-missing-certs`), or issue the certificates first. | 1 |
| 403 | `forbidden` | Your role or scope does not allow the change, or a revert would restore groups of edge nodes (OpenWAF operators only) or another client (organisation-wide credentials only). | Use a credential with the right role, or revert to a version that does not need it. | 1 |
| 404 | `not_found` | The zone or version does not exist, or is outside your organisation or your token's scope. | Check the zone and the version number. | 1 |
| 502 | `dns_out_of_sync` | A delegated zone's DNS could not be published, and putting it back in line with the last committed configuration failed too. The change was rolled back. | Retry; if it persists, write to support@openwaf.dev with the zone. | 1 |

The CLI exits with 2 when it rejects the arguments itself, before calling the API (for example a missing `--reason`), and with 4 when `--wait` runs out of time before every edge node applied the change. See [CLI exit codes](https://developers.openwaf.dev/cli/output-and-exit-codes/#exit-codes).
