412 Precondition Failed
A conditional request's precondition was not met, so the request was not applied.
What 412 means
412 is the failure counterpart of 304. The client attached a condition - If-Match with an ETag, If-Unmodified-Since with a date - and the condition was false, so the server refused to proceed. Nothing was changed.
This is the mechanism for optimistic concurrency control on writes. The client reads a resource and its ETag, sends the ETag back with If-Match on the update, and a 412 tells it that someone else changed the resource in the meantime. The client re-reads and retries, and no update is silently lost.
It is worth preferring over 409 for this specific case, because it says precisely what failed. A 409 tells the client there is a conflict; a 412 tells it the conflict was detected by its own precondition, which is a clearer signal for automated retry.
The related 428 Precondition Required lets a server insist on conditional requests, refusing unconditional writes so that clients cannot accidentally overwrite.
Headers this status expects
- ETag - the current validator, so the client can retry against the new state.
Should a client retry?
Re-read the resource to get its current ETag, then retry the update with that value. Do not retry with the stale ETag.
FAQ
- What causes a 412?
- An If-Match, If-None-Match or If-Unmodified-Since condition that evaluated false - almost always because the resource changed since the client read it. It is a signal to re-read and retry, not a client bug.
- 412 or 409?
- 412 when the failure was specifically a precondition the client supplied, which is a clearer signal for automated retry. 409 for conflicts detected some other way, such as a uniqueness violation.
- How does this prevent lost updates?
- Without a precondition, two clients that both read version 1 and both write will have the second silently overwrite the first. With If-Match, the second write fails with 412, and the client re-reads and reapplies its change.
Often confused with
- 409 Conflict The request conflicts with the current state of the resource.
- 304 Not Modified The cached copy is still current, so the server sent no body.