HTTP 412 Precondition Failed
HTTP 412 Precondition Failed means the server evaluated a condition in the request headers — typically If-Match, If-None-Match, If-Modified-Since, or If-Unmodified-Since — and found it was not satisfied. The server will not apply the request.
Quick reference
| Code | 412 |
|---|---|
| Name | Precondition Failed |
| Category | 4xx Client Errors |
| Specification | RFC 9110 §15.5.13 |
| IANA status | Assigned |
| Client behavior | Re-fetch the current resource state, evaluate the precondition, and if the operation is still valid, retry with updated condition headers. |
| In-depth guide | HTTP 412 conditional request guide → |
What it means
Conditional requests allow clients to make a request that only executes if certain state conditions are true. This enables safe concurrent updates (optimistic locking) and efficient caching validation. 412 is the server's signal that the condition was evaluated and failed — the request was not applied.
The If-Match and ETag pattern
The most common 412 scenario: a client reads a resource and receives an ETag header identifying the resource version. The client wants to update the resource but only if no one else has modified it since it was read. It sends the update with If-Match: [etag]. If the resource has changed (the ETag no longer matches), the server returns 412 instead of applying the update. The client must re-fetch, merge, and retry.
This pattern prevents "lost update" problems in concurrent editing — if two clients read and edit the same resource simultaneously, the second update will fail with 412 rather than silently overwriting the first.
If-Unmodified-Since
If-Unmodified-Since is the timestamp-based equivalent of If-Match. The request only proceeds if the resource has not been modified since the specified date. 412 is returned if the resource has changed since that date. ETag-based conditions are preferred over timestamp-based conditions because ETags are more precise — two modifications in the same second both get different ETags but the same timestamp.
Common causes
Concurrent modification by another client
The most frequent cause. The If-Match ETag was valid when the client read the resource, but another client updated it before this client's write request arrived. The ETag changed, the precondition failed. Re-fetch and reconcile.
Long-lived client cache with stale ETag
A client cached a resource and its ETag a long time ago. When it sends a conditional update based on the stale ETag, 412 occurs because the resource has since been modified. Reduce cache TTL for resources that participate in optimistic locking.
WebDAV locking with If header
WebDAV uses the If header (distinct from If-Match) with lock tokens for conditional request gating. A failed lock token check in a WebDAV request returns 412 rather than 423, depending on the condition structure.
412 vs 409 vs 428
| Code | Meaning | Condition evaluated? |
|---|---|---|
| 412 | Explicit conditional header was present and failed | Yes — If-Match, If-None-Match, etc. |
| 409 | Resource state conflict without explicit condition | No — server detected conflict independently |
| 428 | Conditional header required but missing | N/A — no condition was provided to evaluate |
See also: 409 vs 412 · 412 vs 428
Related resources
On this site: HTTP 412 conditional request guide · HTTP 409 Conflict · HTTP 428 Precondition Required · HTTP 304 Not Modified · All 4xx client errors
Comparisons: 409 vs 412 · 412 vs 428 · 428 vs 412
Standards: RFC 9110 §15.5.13 · IANA Registry · MDN Web Docs: 412