409

Conflict

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

Quick Definition

The request could not be completed because it conflicts with the current state of the resource on the server. This typically happens when two clients try to modify the same resource simultaneously, or when an update is based on an outdated version of the data.

When It Occurs

A 409 Conflict occurs when the server detects that fulfilling the request would create an inconsistent or invalid state. The most common scenario is concurrent editing: two users fetch the same document, both make changes, and the second save attempt conflicts with the first.

Unlike a 400 Bad Request (malformed syntax) or a 403 Forbidden (authorization issue), a 409 means the request itself is valid but cannot be applied given the resource's current state.

Common Causes

  • Concurrent edit conflict - Two users editing the same record simultaneously; the second save is rejected
  • Version/ETag mismatch - The If-Match ETag doesn't match the current resource version
  • Duplicate resource creation - Attempting to create a resource that already exists (e.g., duplicate username or email)
  • State transition violation - Trying to change a resource to an invalid state (e.g., cancelling an already-shipped order)
  • Stale data in client cache - Client operating on outdated data that has since changed on the server
  • Database unique constraint violation - Insert or update violates a unique index in the database

Platform-Specific Notes:

Node.js Common in REST APIs using Mongoose or Sequelize with optimistic locking. Check __v (Mongoose) or version fields.

Nginx Does not generate 409 natively. Proxied from your application backend when conflict detection logic triggers.

Apache WebDAV module returns 409 when creating a resource in a non-existent collection or when lock conflicts occur.

🛠 How to Fix

  1. Fetch the latest resource version - GET the resource again to see its current state and ETag
  2. Compare changes - Diff your intended changes against the current state to identify the conflict
  3. Merge or resolve conflicts - Combine both sets of changes or let the user choose which version to keep
  4. Retry with updated version - Resubmit the request with the correct ETag or version number
  5. Implement optimistic locking - Use ETags or version fields to detect conflicts before they happen
  6. Add conflict resolution UI - Show users a diff view when conflicts occur so they can resolve manually

💻 HTTP Example

# Client tries to update a resource with a stale ETag
PUT /api/documents/42 HTTP/1.1
Host: api.example.com
Content-Type: application/json
If-Match: "v3-abc123"

{"title": "Updated Title", "content": "New content"}

# Server Response (resource was already modified to v4)
HTTP/1.1 409 Conflict
Content-Type: application/json
ETag: "v4-def456"

{
  "error": "Conflict",
  "message": "Resource was modified by another client. Fetch the latest version and retry.",
  "current_version": "v4-def456",
  "your_version": "v3-abc123",
  "statusCode": 409
}

Frequently Asked Questions

What is the difference between 409 Conflict and 412 Precondition Failed? +
A 409 Conflict means the request conflicts with the current state of the resource regardless of conditional headers. A 412 Precondition Failed means the client sent conditional headers (like If-Match or If-Unmodified-Since) and the precondition evaluated to false. Use 409 when the conflict is inherent to the operation itself, and 412 when conditional request headers specifically fail their check.
How do I prevent 409 errors in my API? +
Use optimistic locking with ETags or version numbers. Include the resource's current version in every GET response, and require clients to send it back with update requests via the If-Match header. When versions don't match, return 409 with the current version so the client can fetch, merge, and retry. This pattern prevents silent data overwrites without requiring pessimistic locks.
Should I retry a 409 Conflict automatically? +
Not blindly. A 409 means your request data is based on an outdated state, so retrying the same request will produce the same error. The correct approach is to fetch the latest version of the resource, resolve any conflicts (possibly by merging changes), and then retry with the updated data and version identifier. Automated retry only works if your client can programmatically merge conflicts.

Scan Your Site for HTTP Errors

Detect conflict errors, broken endpoints, and misconfigurations across your website automatically.

Start Free Scan