409 Conflict 4xx
The request could not be completed because it conflicts with the current state of the resource.
What does 409 mean?
A 409 Conflict response means the request itself is understandable and well-formed, but it can't be completed because it conflicts with the current state of the resource on the server. This is different from a validation error (422) — the data isn't necessarily invalid in isolation, it's just incompatible with what already exists.
The classic example: trying to create a new user account with an email address that's already registered. The request is perfectly valid — it's a well-formed "create user" request with a properly formatted email — but it conflicts with the existing state (a user with that email already exists).
How a 409 behaves
- It typically includes a body explaining the conflict — ideally specific enough that the client can understand what state it conflicted with
- It's not cacheable — represents the state at a specific point in time, which can change
- Resolving it usually requires either changing the request or changing the state — either the client adjusts what it's asking for (a different email, a different identifier), or the conflicting state on the server needs to change first (the existing record needs to be deleted/updated)
- It's closely tied to concurrency — 409 is the standard response when two clients try to make conflicting changes to the same resource around the same time (a classic "edit conflict")
Common causes
If you're building the API or website:
- A uniqueness constraint is violated — the request is trying to create something that must be unique (email, username, slug) but a matching record already exists
- An optimistic concurrency check fails — the client is trying to update a resource based on a version/timestamp that's no longer current, because someone else updated it first
- A state machine transition is invalid — e.g., trying to "cancel" an order that's already been "shipped," where the current state doesn't allow the requested transition
If you're calling an API:
- You're trying to create a resource with an identifier (email, username, slug) that already exists
- You're updating a resource using a stale version reference — someone (or something) else modified it since you last fetched it
- You're attempting an action that's invalid given the resource's current status (e.g., trying to "accept" an invitation that's already been accepted or revoked)
If you're a website visitor:
- You're signing up with an email or username that's already registered
- You're trying to perform an action on something that's already been actioned (clicking "accept" on an invite that someone else already accepted, in a multi-user context)
- Two browser tabs/sessions are editing the same thing, and one save conflicts with changes made via the other
How to fix it
As an API/website builder:
- Return a body that clearly explains what conflicted — "a user with this email already exists" is far more useful than a bare 409
- For uniqueness conflicts, consider whether the client needs guidance on what to do next (e.g., "did you mean to log in instead?")
- For concurrency conflicts, implement optimistic locking (version numbers,
ETag/If-Matchheaders) so clients can detect and handle conflicts gracefully rather than silently overwriting each other's changes - Be consistent about 409 vs 422 vs 400 across your API — 409 specifically for "conflicts with existing state," 422 for "fails validation rules," 400 for "malformed request"
As an API consumer:
- For uniqueness conflicts, the fix usually involves choosing a different identifier or recognizing that the resource already exists (and possibly fetching/using the existing one instead of creating a new one)
- For concurrency conflicts, re-fetch the current state of the resource, reconcile any differences with your intended changes, and retry the update against the current version
- Don't blindly retry a 409 with the identical request — unlike a 429 or 503, retrying without changes will produce the same conflict again
As a website visitor:
- If signing up, try logging in instead — the email/username may already be registered to an existing account (possibly your own, from a previous signup)
- If editing something collaboratively, refresh to get the latest version before making changes, especially if you suspect someone else might have edited it recently
409 vs 422 vs 400
| Code | What's wrong | Example |
|---|---|---|
| 400 Bad Request | The request structure/syntax is broken | Malformed JSON |
| 422 Unprocessable Entity | The request is well-formed, but a value fails validation rules | email: "not-an-email" |
| 409 Conflict | The request is well-formed and the values are individually valid, but it conflicts with the resource's current state | email: "[email protected]" — but that email is already registered |
A useful way to think about it: 422 is about whether a value is valid on its own; 409 is about whether the request is valid given everything else that currently exists.
Real-world examples
Many user-registration APIs return 409 when a signup request uses an email or username that's already taken — distinct from a 422 that might be returned if the email format itself were invalid. APIs implementing optimistic concurrency control (common in collaborative editing tools, project management APIs, etc.) return 409 when a client attempts to update a resource using an outdated version identifier, signaling "someone else changed this since you last looked — please refresh and try again."
SEO implications
409 is almost exclusively relevant to form submissions and API write operations (POST/PUT/PATCH), not regular page navigation — it has no direct SEO implications for content pages.
FAQ
What's the difference between 409 and 422?
422 means a value in the request fails validation on its own terms (wrong format, out of range). 409 means the request is individually valid but conflicts with the current state of the server — most commonly, something the request is trying to create or claim already exists, or the resource has changed since the client last saw it.
Will retrying a 409 request ever succeed without changes?
Generally no — a 409 means the request conflicts with the current state. Unless that state changes (the conflicting resource is deleted, or the resource is updated to a version your request is compatible with), an identical retry will produce the same conflict.
What is "optimistic concurrency control" and how does it relate to 409?
It's a pattern where clients include a version identifier (a number, timestamp, or ETag) when updating a resource, asserting "I'm updating based on version X." If the server's current version doesn't match (because someone else updated it first), it returns 409 rather than silently applying the update and overwriting the other change.
Is 409 used for "this email is already taken" type errors?
Often, yes — though some APIs use 422 for this instead, treating "must be unique" as a validation rule on the field. Both approaches exist in practice; 409 more precisely frames it as a state conflict ("this already exists") rather than a value-level validation issue.
How should I handle a 409 in my frontend application?
For uniqueness conflicts, surface a clear message ("This email is already registered — try logging in instead"). For concurrency conflicts, the best practice is typically to refresh the data, show the user what changed, and let them decide how to proceed — rather than silently discarding either version of the change.
Fun fact
409 sits at an interesting intersection of HTTP semantics and database concepts — it's essentially HTTP's way of expressing what databases call a "constraint violation" or "optimistic lock failure," translating concepts from the data layer directly into a status code that API consumers can handle without needing to understand the underlying storage implementation.