Error reference

version_conflict

HTTP 412 retryable: false REST and MCP

The version or revision you sent does not match the resource's current one, so your update was computed against state that is no longer there.

Why it happens

Updates to policies and webhook endpoints are optimistically concurrent: you send the version you read, and the write only proceeds if it still matches under a row lock. This is not a general-purpose staleness warning, it is targeted at the settings whose silent overwrite would be dangerous. A policy edit that clobbers a block rule someone added a minute ago would quietly widen who an agent can email. The approval path uses the same idea with a content hash instead of a counter: a draft whose payload hash no longer matches the one the approval was granted against cannot be released under that approval.

Every condition below was read in the implementation at the file and line given. They are the branches that raise this code, not a summary of what the name suggests.

How to fix it

  1. Re-read the resource, re-apply your change to the version you just read, and send the new version number. Do not increment the number you were holding.
  2. Show the current state to whoever is editing before saving again. The message says to refresh and review, and for a sending policy that review is the point.
  3. For an approval, request a fresh one after editing the draft. The approval is bound to the exact content that was shown to the approver.
  4. Treat a missing policy as version 0. An inbox with no inbox-scoped policy of its own is at version 0, not version 1.

Why it works this way

Binding an approval to a payload hash rather than to a draft id is the substantive choice here. It means approving a draft approves that text, and editing after approval invalidates it, which is what makes the human decision meaningful rather than a rubber stamp on a mutable object.

Messages you will see

The message field is written for a human reading a log and is not a contract value. Branch on code instead. These are the exact strings this code is sent with today, listed so that a search for one of them lands here.

Where it appears

These are the documented surfaces that raise it. The REST base is https://api.emailforagents.ai/v1, and the remote MCP endpoint is https://mcp.emailforagents.ai/mcp.

The response

Read request_id off the body or the x-request-id header before doing anything else. It is the only handle on one specific attempt, and for a 503 it is the only handle at all, because the underlying detail stays server-side.

HTTP/1.1 412
content-type: application/json
x-request-id: req_...

{
  "error": {
    "code": "version_conflict",
    "message": "These settings changed. Refresh and review the current policy before saving.",
    "request_id": "req_...",
    "retryable": false
  }
}

Verified against packages/domain/src/customer-controls.ts:185. The status comes from ERROR_STATUS in packages/contracts/src/errors.ts, which is the one place a code is mapped to a status.

All error codes · Documentation · Quickstart