# HTTP 412 Precondition Failed — Meaning, Causes & Fixes

> A condition in the request headers, such as If-Match, didn't hold, so nothing was changed.

412 is how conditional writes fail safely. A client sends `If-Match: "<etag>"` or `If-Unmodified-Since` to say 'only apply this if the resource is still the version I saw'. If someone else changed it in the meantime, the server refuses with 412 instead of silently overwriting their work.

- Class: 4xx Client Error
- Retry: No — change the request first
- Cacheable by default: no
- Defined in: [RFC 9110 §15.5.13 — 412 Precondition Failed](https://www.rfc-editor.org/rfc/rfc9110.html#section-15.5.13)

## Example response

```http
HTTP/1.1 412 Precondition Failed
Content-Type: application/json
Content-Length: 31

{"error":"Precondition Failed"}
```

## Common causes

- Optimistic concurrency: the ETag in `If-Match` is stale.
- Cloud storage uploads with a version or generation precondition that no longer matches.
- `If-None-Match: *` on a create, when the resource already exists.

## How to fix it

1. Re-fetch the resource to get the current ETag, re-apply the change and retry.
2. Show users a 'someone else edited this' prompt instead of retrying blindly.

## Send a 412 from your server

### Express

```
res.status(412).json({ error: "Precondition Failed" });
```

### Next.js route handler

```
return Response.json({ error: "Precondition Failed" }, { status: 412 });
```

### Flask

```
return {"error": "Precondition Failed"}, 412
```

### Go net/http

```
http.Error(w, "Precondition Failed", http.StatusPreconditionFailed)
```

### nginx

```
return 412;
```

## FAQ

### 412 vs 409?

412: a precondition the client sent (If-Match and friends) failed. 409: the server found a conflict without one.

### 412 vs 428?

412: you sent a condition and it failed. 428: you didn't send one and the server requires it.

## Related status codes

- [409 Conflict](https://www.devkult.com/http/409.md)
- [428 Precondition Required](https://www.devkult.com/http/428.md)
- [304 Not Modified](https://www.devkult.com/http/304.md)

Open the interactive page: https://www.devkult.com/http/412