HTTP status · 4xx — client error
412 Precondition Failed
A conditional request failed because the resource no longer matches the client’s validator.
Key facts
| Class | 4xx — client error |
|---|---|
| Standard | RFC 9110 §15.5.13 |
| Trigger | If-Match, If-None-Match, If-Unmodified-Since |
| Body | Usually a short explanation |
| Retryable | After re-reading the resource |
| Related header | ETag |
Optimistic concurrency in one status code
A client reads a resource, receives an ETag, then sends an update with If-Match: "<etag>". If the resource changed in between, the server answers 412 and the write is rejected. This prevents two editors from silently overwriting each other.
If-None-Match: * on a PUT is the inverse: it fails with 412 if the resource already exists, which turns PUT into create-only.
How to recover
Do not blindly retry the same request. Fetch the current representation, merge the user’s intent, send a new request with the fresh ETag and show the user what changed. If the conflict is trivial, a bounded retry loop is acceptable; an unbounded one turns a conflict into a livelock.
Frequently asked questions
Is 412 the same as 409 Conflict?
No. 409 signals a semantic conflict with the current state; 412 signals that a precondition header evaluated to false.
Why did my PUT return 412?
The If-Match ETag no longer matches because the resource changed after you read it.
Should 412 include the current representation?
It may, and doing so helps the client merge. The standard does not require it.