# HTTP 409 Conflict — Meaning, Causes & Fixes

> The request conflicts with the current state of the resource.

409 means the request was valid on its own but clashes with the resource's current state. The classic cases are duplicates — creating a user whose email already exists — and edit conflicts — updating a document someone else has changed. The response body should explain the conflict so the client can resolve it.

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

## Example response

```http
HTTP/1.1 409 Conflict
Content-Type: application/json
Content-Length: 20

{"error":"Conflict"}
```

## Common causes

- Creating something that must be unique and already exists.
- Concurrent edits: optimistic locking spotted a stale version.
- Invalid state transitions, such as cancelling an order that already shipped.

## How to fix it

1. Fetch the current state, merge or let the user choose, then retry.
2. For edits, use ETags with `If-Match`; a mismatch returns 412, which is the more precise signal.
3. Return details in the body: which field conflicted, and the current version.

## Send a 409 from your server

### Express

```
res.status(409).json({ error: "Conflict" });
```

### Next.js route handler

```
return Response.json({ error: "Conflict" }, { status: 409 });
```

### Flask

```
return {"error": "Conflict"}, 409
```

### Go net/http

```
http.Error(w, "Conflict", http.StatusConflict)
```

### nginx

```
return 409;
```

## FAQ

### 409 or 422 for a duplicate email?

Both are used. 409 says it conflicts with existing state; 422 says the submitted data is invalid. 409 is the more common choice for uniqueness violations.

### 409 vs 412?

412 is a precondition the client stated (If-Match) that failed. 409 is the server detecting a conflict on its own.

## Related status codes

- [412 Precondition Failed](https://www.devkult.com/http/412.md)
- [422 Unprocessable Content](https://www.devkult.com/http/422.md)
- [400 Bad Request](https://www.devkult.com/http/400.md)

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