428 Precondition Required: Conditional Headers Are Mandatory
If-Match with the current ETag) in the request. If the client does not provide these headers, the server returns 428, telling the client to retrieve the current state and include the proper preconditions.
Why 428 Exists
In concurrent environments, two clients may try to update the same resource simultaneously. Without proper locking or conditional requests, the last update could overwrite the first (lost update problem). By requiring conditional headers like If-Match, the server ensures that the client's update is based on the latest version. If the resource has changed in the meantime, the request fails (with 412 Precondition Failed) and the client must retry.
428 is used when the client doesn't send any conditional headers, whereas 412 is used when the client sends conditional headers but they evaluate to false.
Common Causes of 428 Errors
| Cause | Example | How to Fix |
|---|---|---|
| Missing conditional headers | PUT request without If-Match or If-None-Match. | Add If-Match with the current ETag. |
| Stale client state | Client doesn't know the current ETag. | GET the resource first to obtain the ETag, then retry the update. |
| Server requires preconditions for safety | Server policy mandates conditional writes. | Always use conditional requests for updates. |
Example: 428 Response
A client attempts to update a resource without any conditional headers:
How to Fix 428 Errors
- If you're a client developer: First send a GET request to the resource to retrieve the current ETag (in the
ETagheader). Then, include the ETag in theIf-Matchheader of your update request. For example:If-Match: "abc123". If you are creating a new resource (POST), you may useIf-None-Match: *to ensure the resource doesn't already exist. - If you're a server developer: Use 428 to enforce conditional updates when it's critical to avoid lost updates. Ensure you send clear error messages so clients know how to fix the request. Also, provide the ETag in GET responses so clients can use it.
- If you're an endβuser: This error is typically not visible in browsers; it's an APIβlevel error. If you see it, it's likely a bug in the application you're using. Contact the developer.
Conditional Headers Overview
- If-Match β only perform the request if the resource's ETag matches the given value (for updates).
- If-None-Match β only perform the request if the resource's ETag does NOT match (for creation, prevent duplicates).
- If-Modified-Since β only perform if the resource has been modified since the given date.
- If-Unmodified-Since β only perform if the resource has NOT been modified since the given date.
Frequently Asked Questions
Is 428 a client error or a server error?
It's a client error (4xx) because the client failed to include the required conditional headers. The server is working correctly but has a policy of requiring preconditions for certain operations.
What is the difference between 428 and 412?
428 means the client did not send any conditional headers, and the server requires them. 412 means the client sent conditional headers, but they evaluated to false (e.g., the ETag doesn't match).
Should I always use 428 in my APIs?
Only if you want to enforce conditional updates. It's a good practice for APIs that require strong consistency, but many APIs simply accept the request and use the latest version (or return 409/412). Evaluate your use case.