HTTP

Status Code

409 Conflict

Learn what 409 Conflict means when requests conflict with server state. Understand concurrent updates, version conflicts, and optimistic locking strategies.

4 min read intermediate Try in Playground

What is a 409 Error?

TL;DR: 409 Conflict means your request conflicts with current state. Fetch the latest version and retry.

A 409 Conflict status code means your request can’t be completed because it conflicts with the current state of the resource. Think of it like trying to book a hotel room that someone else just reserved—the room exists and your request is valid, but there’s a conflict with what’s already happened.

The server understood your request perfectly, but completing it would create an inconsistent or impossible situation.

When Does This Happen?

You’ll encounter a 409 error in these common situations:

1. Duplicate Resource Creation

You try:     POST /users {"email": "john@example.com"}
But exists:  User with john@example.com already exists
Result:      409 Conflict

2. Version Conflicts (Optimistic Locking)

You edit:    PUT /posts/123 {"version": 5, "title": "New Title"}
But current: Post version is now 6 (someone else edited it)
Result:      409 Conflict

3. Business Rule Violations

You try:     DELETE /orders/456
But status:  Order is already shipped (can't delete shipped orders)
Result:      409 Conflict

4. Resource State Conflicts

You try:     POST /accounts/789/withdraw {"amount": 1000}
But balance: Account only has $500
Result:      409 Conflict

5. Concurrent Modification

User A:      Updates product price to $100
User B:      Simultaneously updates same product to $200
Result:      409 Conflict for the second request

Example Response

When a conflict occurs, the server responds like this:

HTTP/1.1 409 Conflict
Content-Type: application/json
Content-Length: 156

{
  "error": "Conflict",
  "message": "Email address already exists",
  "details": "A user with email 'john@example.com' is already registered",
  "existing_resource": "/users/123"
}
```text

Key parts of this response:

- **409 Conflict** - The status code and reason
- **Content-Type** - Format of the error details
- **Body** - Specific information about what conflicted
- **Details** - How to understand or resolve the conflict

## Real-World Examples

**Example 1: User Registration Conflict**

```http
POST /api/users HTTP/1.1
Host: example.com
Content-Type: application/json

{
  "username": "johndoe",
  "email": "john@example.com",
  "password": "secret123"
}

Response:

HTTP/1.1 409 Conflict
Content-Type: application/json

{
  "error": "Username conflict",
  "message": "Username 'johndoe' is already taken",
  "suggestions": ["johndoe2", "johndoe2024", "john_doe"],
  "check_availability": "/api/users/check-username"
}
```text

**Example 2: Version Conflict**

```http
PUT /api/documents/456 HTTP/1.1
Host: docs.example.com
Content-Type: application/json
If-Match: "version-5"

{
  "title": "Updated Document",
  "content": "New content here"
}

Response:

HTTP/1.1 409 Conflict
Content-Type: application/json
ETag: "version-7"

{
  "error": "Version conflict",
  "message": "Document has been modified by another user",
  "current_version": 7,
  "your_version": 5,
  "latest_content": "/api/documents/456"
}
```text

## How to Handle 409 Errors

**As a Developer:**

- Check the response body for conflict details
- Implement retry logic with updated data
- Use optimistic locking with version numbers
- Provide clear error messages to users
- Offer alternative solutions when possible

**As a User:**

- Refresh the page to get the latest data
- Try again with different values (like a new username)
- Check if someone else made changes first
- Contact support if the conflict seems wrong

## 409 vs Other Similar Codes

| Code    | Meaning                              | When It Happens                                   |
| ------- | ------------------------------------ | ------------------------------------------------- |
| **409** | Request conflicts with current state | Data collision or business rule violation         |
| **400** | Bad request format                   | Request syntax or format is wrong                 |
| **422** | Unprocessable entity                 | Request format is correct but data is invalid     |
| **423** | Resource locked                      | Resource is temporarily locked by another process |
| **412** | Precondition failed                  | If-Match or similar header condition not met      |

## Common Conflict Scenarios

**❌ Not handling duplicate creation**

```javascript
// This might create duplicates
fetch('/api/users', {
  method: 'POST',
  body: JSON.stringify({ email: 'user@example.com' })
})

✅ Check for conflicts first

// Check if user exists before creating
const checkResponse = await fetch('/api/users/check?email=user@example.com')
if (checkResponse.status === 200) {
  throw new Error('User already exists')
}

// Safe to create now
const createResponse = await fetch('/api/users', {
  method: 'POST',
  body: JSON.stringify({ email: 'user@example.com' })
})
```text

**❌ Ignoring version conflicts**

```javascript
// This might overwrite someone else's changes
fetch('/api/posts/123', {
  method: 'PUT',
  body: JSON.stringify({ title: 'New Title' })
})

✅ Using optimistic locking

// Get current version first
const current = await fetch('/api/posts/123')
const { version, ...data } = await current.json()

// Update with version check
const response = await fetch('/api/posts/123', {
  method: 'PUT',
  headers: { 'If-Match': `"version-${version}"` },
  body: JSON.stringify({ ...data, title: 'New Title' })
})

if (response.status === 409) {
  // Handle conflict - maybe refresh and try again
  console.log('Someone else updated this post')
}

Try It Yourself

Visit our request builder and create a conflict:

  1. Set method to POST
  2. Set path to /api/users
  3. Try creating the same user twice
  4. Watch the 409 response on the second attempt

Frequently Asked Questions

What does 409 Conflict mean?

A 409 error means your request conflicts with the current state of the resource. Common causes include duplicate entries, version conflicts, or trying to modify a resource that has changed since you last read it.

How do I fix a 409 Conflict error?

Fetch the latest version of the resource, resolve the conflict by merging changes, and retry with the updated data. For duplicate errors, check if the resource already exists before creating.

What is the difference between 409 and 400?

409 means your request is valid but conflicts with existing data. 400 means your request is malformed or invalid. With 409, the syntax is correct but the operation cannot complete due to state conflicts.

What is optimistic locking and how does it relate to 409?

Optimistic locking uses version numbers or ETags to detect concurrent modifications. When you try to update with an outdated version, the server returns 409 to prevent overwriting someone elses changes.

Keep Learning