HTTP 409 Conflict
Updated Free mock REST & WebSocket APIs
HTTP 409 Conflict — The request conflicts with the current state of the resource.
- Class
- 4xx Client Error
- Defined in
- RFC 9110 §15.5.10
- Official
- Yes (IANA registry)
- Cacheable by default
- No (unless Cache-Control/Expires say so)
- Safe to retry
- Not without changing the request
Try it: get a real 409 response
Our test endpoint answers every request with 409 Conflict.
curl -i https://mockfox.dev/api/status/409Use it in tests, health-check monitors or to see how your client handles a 409. Add ?delay=2000 to slow it down.
What does HTTP 409 mean?
409 Conflict means the request couldn't be completed because it conflicts with the current state of the target resource. The client can usually resolve the conflict and resubmit, so the response body should explain what conflicted.
When is 409 used?
- Creating something that must be unique and already exists (a username or email already registered).
- Concurrent edits: saving changes based on an outdated version of a document.
- A state transition that isn't allowed (cancelling an order that has already shipped).
- Git hosting and package registries rejecting a push or publish of an existing version.
Common causes of a 409
- Someone (or another tab/device) changed the resource since you loaded it.
- A duplicate submission — e.g. double-clicking a submit button.
- A unique constraint in the database.
How to fix 409 Conflict
If you're visiting the site
- Refresh the page to load the latest version, then make your change again.
- If signing up, the email or username may already be in use — try logging in or resetting your password.
If you run the site or API (developers)
- Return a body that names the conflict, e.g.
{"error":"email_taken"}or the current version. - For lost-update protection use ETags with
If-Match, answering 412 when they don't match (409 is fine for domain conflicts). - Map database unique-constraint violations to 409 instead of letting them bubble up as 500.
- Use idempotency keys so retried requests don't produce spurious conflicts.
Returning or handling 409: server examples
Express
app.post("/api/users", async (req, res) => {
try {
res.status(201).json(await db.users.create(req.body));
} catch (e) {
if (e.code === "23505") // Postgres unique_violation
return res.status(409).json({ error: "email_taken" });
throw e;
}
});Next.js
// app/api/example/route.ts (Next.js App Router)
export async function PATCH(req: Request) {
const { version, ...changes } = await req.json();
const doc = await getDoc();
if (doc.version !== version)
return Response.json({ error: "conflict", current: doc }, { status: 409 });
return Response.json(await saveDoc(changes));
}Example 409 response
HTTP/1.1 409 Conflict
Content-Type: application/json
{"error":"email_taken","message":"An account with this email already exists."}Related status codes
- 412 Precondition FailedA condition in the request headers (If-Match, If-Unmodified-Since…) evaluated to false.
- 422 Unprocessable ContentThe request is well-formed, but its contents fail validation.
- 400 Bad RequestThe server can't process the request because it's malformed or invalid.
Related tools
Frequently asked questions
409 or 400 for a duplicate?
409 is the better fit: the request itself is valid, but it conflicts with existing data. 400 suggests the request is malformed.
409 or 422?
Use 422 when the input is invalid in itself (an email that's not an email). Use 409 when valid input clashes with the current state (an email that's already taken).
409 or 412?
412 Precondition Failed is specifically for failed conditional headers (If-Match, If-Unmodified-Since). 409 covers other state conflicts.