Browser showing a 409 Conflict HTTP error
# website errors# troubleshooting

409 Conflict Error: What It Means and How to Fix It

A 409 Conflict error means the server understood your request, but it can't process it because it conflicts with the current state of the target resource. This is one of the more specific HTTP error codes — it's telling you not just that something went wrong, but that the data you're trying to submit clashes with what already exists.

You'll encounter 409 errors most often in APIs, version-controlled systems, and applications where multiple users or processes can modify the same resource simultaneously.

What Does a 409 Conflict Mean?

A 409 status code indicates that the request could not be completed due to a conflict with the resource's current state. The server is saying: "I understand what you want to do, and I could do it under different circumstances, but right now there's a conflict that prevents it."

Unlike a 422 Unprocessable Entity where the data itself is malformed, a 409 means the data is valid — it just clashes with something that already exists or with a business rule.

Common scenarios:

  • Trying to create a user with an email address that's already registered.
  • Attempting to update a resource that has been modified by someone else since you last fetched it (optimistic locking conflict).
  • Uploading a file that conflicts with an existing version.
  • Sending a request that violates a uniqueness constraint in the database.

Common Causes of a 409 Error

1. Duplicate Resource Creation

The most common trigger. Your application tries to create a resource that already exists or violates a unique constraint.

# Example: trying to create a user with a duplicate email
curl -X POST https://api.example.com/users \
    -H "Content-Type: application/json" \
    -d '{"email": "[email protected]", "name": "New User"}'

# Response: 409 Conflict
# {"error": "A user with this email already exists"}

This typically maps to a database uniqueness violation:

# PostgreSQL error behind the scenes
# ERROR: duplicate key value violates unique constraint "users_email_key"

2. Optimistic Concurrency Conflicts

Many APIs use optimistic locking to prevent lost updates. When you fetch a resource, you receive a version identifier (often an ETag or a version number). When you update it, you send that version back. If someone else updated the resource in the meantime, the versions don't match and you get a 409.

# Fetch the resource with its ETag
curl -i https://api.example.com/documents/123
# ETag: "v5"

# Try to update with the ETag
curl -X PUT https://api.example.com/documents/123 \
    -H "If-Match: v5" \
    -H "Content-Type: application/json" \
    -d '{"title": "Updated Title"}'

# If someone else updated it (now at v6), you get 409

3. State Machine Violations

Some resources follow a specific lifecycle. For example, you can't cancel an order that's already been delivered, or you can't publish a document that's been archived. Attempting an invalid state transition returns a 409.

4. File or Version Conflicts

Version control systems and file storage APIs return 409 when you try to push changes that conflict with the current state. Git users will recognise this as the API equivalent of a merge conflict.

5. Race Conditions

Two requests hitting the server at nearly the same time, both trying to modify the same resource. The first one succeeds; the second gets a 409 because the resource's state changed between when the request was composed and when it was processed.

How to Fix a 409 Conflict Error

Step 1: Read the Response Body

A well-designed API will tell you exactly what the conflict is. Check the response body:

curl -s -X POST https://api.example.com/users \
    -H "Content-Type: application/json" \
    -d '{"email": "[email protected]"}' | jq .

The response should explain whether it's a duplicate key, a version mismatch, or a state conflict.

Step 2: Handle Duplicate Resources

If you're hitting unique constraint violations, check if the resource exists before trying to create it, or use an upsert pattern:

# Check if the resource exists first
curl -s -o /dev/null -w "%{http_code}" https://api.example.com/users?email=[email protected]

On the server side, many databases support "insert or update" operations:

-- PostgreSQL upsert
INSERT INTO users (email, name) VALUES ('[email protected]', 'Test User')
ON CONFLICT (email) DO UPDATE SET name = EXCLUDED.name;

Step 3: Implement Retry Logic for Concurrency Conflicts

For optimistic locking conflicts, the standard fix is to re-fetch the resource, get the latest version, apply your changes, and retry:

# 1. Fetch the latest version
curl -i https://api.example.com/documents/123
# Get the new ETag from the response

# 2. Retry the update with the new ETag
curl -X PUT https://api.example.com/documents/123 \
    -H "If-Match: v6" \
    -H "Content-Type: application/json" \
    -d '{"title": "Updated Title"}'

Step 4: Validate State Transitions

If you're getting 409s from invalid state transitions, check the resource's current state before attempting the operation:

# Check the current state
curl -s https://api.example.com/orders/456 | jq '.status'
# "delivered"

# Don't try to cancel a delivered order

Step 5: Add Database-Level Conflict Handling

On the server side, catch constraint violations and return meaningful 409 responses:

# Check your application logs for the underlying database error
grep -i "duplicate key\|unique constraint\|conflict" /var/log/app/error.log

How Domain Monitor Can Help

While 409 errors are typically application-level issues rather than infrastructure failures, a sudden spike in 409 responses can indicate a deeper problem — such as a corrupted database index, a race condition introduced by a new deployment, or a misconfigured API endpoint returning 409 for all requests instead of just conflicting ones.

Domain Monitor checks your endpoints every minute from multiple locations worldwide. If your API or web application starts returning 409 errors (or any unexpected status codes) where it should be returning 200s, you'll be alerted immediately via email, SMS, or Slack. You can set up downtime alerts for your critical endpoints and use website monitoring to ensure your application is responding correctly across all regions.

Quick Summary

CauseFix
Duplicate resource (unique constraint)Check existence first, or use upsert
Optimistic locking mismatchRe-fetch, get latest version, retry
Invalid state transitionCheck resource state before the operation
Race conditionImplement proper locking or retry logic
File/version conflictMerge changes, then resubmit

A 409 is one of the more helpful HTTP errors — it tells you specifically that there's a data conflict, not just a vague server error. Read the response body, resolve the conflict, and retry.

More posts

Wildcard vs SAN vs Single-Domain SSL Certificates: Which Do You Need?

Wildcard, SAN (multi-domain), and single-domain SSL certificates cover different use cases. Here's a clear comparison to help you pick the right type — and avoid paying for coverage you don't need.

Read more
Why DNS Works in One Location but Fails in Another

DNS resolves correctly from your office but fails for users in other countries or on different ISPs. Here's why geographic DNS inconsistency happens and how to diagnose which layer is causing it.

Read more
Registrar Lock vs Transfer Lock: What's the Difference?

Registrar lock and transfer lock are often confused — and disabling the wrong one leaves your domain vulnerable. Here's a clear breakdown of what each does and when to use them.

Read more

Subscribe to our PRO plan.

Looking to monitor your website and domains? Join our platform and start today.