{ }HttpStatus.com

412 Precondition Failed

A conditional header such as If-Match or If-Unmodified-Since evaluated to false against the resource's current state.

Defined in RFC 9110 §15.5.13

What 412 means

412 Precondition Failed means one of the conditional headers the client sent, If-Match, If-None-Match, If-Modified-Since, or If-Unmodified-Since, evaluated to false against the resource's current state, so the server declined to perform the requested method. Conditional headers let a client state an assumption about the resource, such as only doing this if it still matches this ETag, and have the server enforce that assumption atomically, rather than the client checking and acting in two separate, race-prone steps.

The most common real use is protecting against lost updates: a client fetches a resource along with its ETag, later sends a PUT or DELETE with If-Match set to that ETag, and if another process has modified the resource in the meantime, the ETag no longer matches and the server returns 412 instead of silently applying the write over someone else's change. If-Unmodified-Since works the same way using a timestamp rather than an opaque tag.

412 is easy to confuse with 304 Not Modified, but the two apply to genuinely different situations: 304 is a successful response to a conditional GET using If-None-Match, telling the client its cached copy is still perfectly fine to use, while 412 is a failure response to a conditional unsafe method such as PUT, DELETE, or PATCH, telling the client that its stated assumption about the resource's current state turned out to be wrong.

Common causes

  • The resource was modified by another client or process since this client last fetched its ETag or Last-Modified value.
  • The client sent a stale If-Match header captured from an outdated cached copy.
  • A concurrent write changed the resource's state between the client's read and its conditional write.
  • A caching bug or stale local state produced an incorrect precondition header value.

How to fix a 412

If you are the client (browser user or API caller)

  • Refetch the resource's current ETag or Last-Modified value and reapply the change before retrying.
  • Merge the intended change with the latest server-side state rather than overwriting it outright.
  • Remove the precondition header only if an unconditional write is genuinely intended, since that reintroduces the lost-update risk.

If you run the server

  • Return the resource's current ETag or Last-Modified value in the 412 response so the client can resynchronize.
  • Document precondition support clearly for every PUT, PATCH, and DELETE endpoint that uses it.
  • Apply precondition checks consistently across mutating endpoints to guard against lost-update race conditions.

Example

DELETE /files/report.pdf HTTP/1.1
Host: api.example.com
If-Match: "a1b2c3"

HTTP/1.1 412 Precondition Failed
Content-Type: application/json

{"error": "precondition_failed", "current_etag": "d4e5f6"}
The If-Match ETag no longer matches the file's current version, so the delete is rejected rather than applied blindly.

Try it live

Our free status responder returns a real HTTP 412 you can point tests, monitors or a browser at.

GET https://mcp.httpstatus.com/status/412

Related status codes

Tools for debugging this