412 Precondition Failed
A conditional header on the request evaluated to false, so the server did not perform the method.
Status
HTTP/1.1 412 Precondition Failed
Details
- Category: 4xx
- Status: Standard. Registered with IANA and defined by a current standards-track RFC.
- Specification: RFC 9110 §15.5.13
- Cacheable: Not cacheable
- Response body: Allowed
- Retry: Retry only after changing the request
412 is how optimistic concurrency control fails safely. A client sends If-Match with the ETag it last saw, and if the resource has changed since then the server refuses the write instead of silently overwriting somebody else's update.
It also arises from If-Unmodified-Since and from If-None-Match on unsafe methods. The write did not happen, so no state changed: the client can re-read and try again.
Headers
- ETag: The current validator, so the client can see what it needs to match.
Common causes
- If-Match carried a stale ETag because another client wrote first.
- If-Unmodified-Since named a time earlier than the resource's last modification.
- A cache or proxy revalidated with a validator the origin no longer recognizes.
How to fix it
As the client
- Re-fetch the resource, take the new ETag, merge your change, and resubmit.
- Do not strip the conditional header to force the write through. That reintroduces the lost update the precondition prevented.
As the server
- Return the current ETag with the 412 so the client can recover in one round trip.
- Use 428 to require preconditions on endpoints where unconditional writes are dangerous.
Examples
PUT /api/docs/91 HTTP/1.1
Host: api.example.com
If-Match: "v3"
Content-Type: application/json
{"title":"Updated"}
HTTP/1.1 412 Precondition Failed
ETag: "v5"