# X_STATE_CONFLICT

## Means

the row changed after the read this transition was decided on

## Typical cause

the lost update, caught: two callers both read `pending`, both found the move legal, and the second one's statement carried `status = 'pending'` in its predicate and matched nothing. Or the row is still in `from` but a column the deciding policy read (`move.observed`, #702) changed — `cause` names the column, never its value. The state in `cause` is read back AFTER the refusal, so it is a diagnosis and never the decision — the decision was the statement, and it was atomic. **409 and not 422**: nothing is wrong with the request, the identical one succeeds a moment later, and re-read-and-retry is precisely what a 409 tells a client to do

## Fix

re-read the row and decide again against the state `cause` names: `orders.findById(id)` — a transition names the state it expects, so a stale read is refused rather than overwritten

[Entity and database](/error-codes#entity-and-database)
