409 - Conflict
HTTP 409 Conflict means the request conflicts with the current state of the target resource.
Last reviewed: April 21, 2026|Source-backed guidance under our editorial policy
Start Here
Use the closest compare guide, playbook, or adjacent error page to narrow the decision faster before you start changing production systems.
This page is part of the Error Reference library. Learn more about the project or report a correction.
What Does Conflict Mean?
The request is valid, but applying it would collide with the resource’s current state, uniqueness rules, or business workflow. Recovery depends on whether the caller needs to refresh state, merge changes, adopt an already-created resource, or move to a different workflow transition.
Common Causes
- -Concurrent writes hit a unique key or stale-version guard and the second mutation loses.
- -If-Match or version state is stale after another writer updated the same resource.
- -Create retries replay without an idempotency key and collide with a resource already created successfully.
- -A workflow attempts a transition that conflicts with the resource’s current business state.
- -Clients hold mutable state too long and submit updates based on an old snapshot.
How to Fix Conflict
- 1Fetch the latest resource representation, then retry with current precondition tokens such as
If-Matchor version fields. - 2Separate stale-version conflicts from duplicate-create conflicts before choosing a retry path.
- 3Return machine-readable conflict reasons so callers can merge, refresh, or adopt existing state instead of blind-retrying.
- 4Enforce idempotency controls and deterministic write ordering for mutating flows.
Step-by-Step Diagnosis for Conflict
- 1Capture conflict metadata: version, ETag, lock, duplicate key, workflow state, or idempotency collision details.
- 2Re-read resource state immediately before mutation to detect stale client assumptions.
- 3Trace concurrent writers and sequencing decisions through request IDs and workflow events.
- 4Determine whether the 409 is caused by stale state, uniqueness collision, or invalid business-state transition.
- 5Retest with explicit preconditions and idempotency keys to confirm the conflict path is eliminated.
Seen in Production
- -Two operators edit the same ticket from stale UI snapshots, and the second save returns 409 after the first write lands.
- -A client retries create without an idempotency key, and the duplicate request collides with an already-created resource.
- -An order workflow tries to cancel after fulfillment started, and the service rejects the transition with 409.
- -A mobile client reconnects after a long offline period and submits an update based on an outdated version.
State Version and Preconditions
- -Inspect precondition signals used by the endpoint (example: stale
If-MatchETag conflicts with current document version). - -Verify clients are not caching mutable state too long before writes (example: UI edits based on a 10-minute-old snapshot).
Workflow Ordering and Uniqueness Conflicts
- -Trace business-state transitions for invalid order (example: shipping update sent before payment capture reaches final state).
- -Audit uniqueness and idempotency constraints (example: duplicate create uses the same external order ID or idempotency key).
Decision Shortcut: Refresh, Merge, or Adopt
- -If the resource changed since the client last read it, refresh and merge before retrying.
- -If the operation already succeeded once, adopt the existing resource through idempotency or duplicate-detection logic instead of creating again.
- -If the business workflow disallows the transition entirely, repair the workflow path rather than replaying the same action.
Wrong Fix to Avoid
- -Do not blindly retry mutating requests without re-reading state first.
- -Do not suppress uniqueness or precondition checks just to reduce 409 rates.
- -Do not treat every 409 as the same conflict class; stale versions, duplicate creates, and invalid transitions recover differently.
Implementation Examples
2026-04-21T12:08:11Z requestId=req_90fa21 resource=ticket/482
attemptedVersion=17 currentVersion=18 status=409 reason=version_mismatch
message="resource state changed before update could be applied"const snapshot = await fetch('/api/tickets/482');
const currentEtag = snapshot.headers.get('ETag');
const response = await fetch('/api/tickets/482', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'If-Match': currentEtag,
},
body: JSON.stringify({ status: 'closed' }),
});{
"requestId": "req_create_8bf1",
"status": 409,
"reason": "duplicate_external_id",
"externalId": "order-88421",
"existingResourceId": "orders/2026-88421",
"idempotencyKey": "idem_4f901d"
}rg 'status=409|duplicate_external_id|version_mismatch|invalid_transition' application.logIncident Timeline
12:07 UTC
A client decides based on state that is no longer current
Signal: UI snapshots, retry paths, or parallel workflows prepare a mutation using stale or conflicting assumptions about current state.
Why it matters: The useful question is which assumption about the target state became false before the write landed.
12:08 UTC
The server rejects the mutation with 409
Signal: A version token, uniqueness constraint, or workflow-state guard detects that the action conflicts with current state.
Why it matters: This is protecting consistency. The operation needs reconciliation, not blind repetition.
12:09 UTC
Retries or duplicate creates make the conflict noisier
Signal: Clients replay the same request without refreshing state or attaching idempotency identity.
Why it matters: Conflict volume rises when retries preserve the same stale assumptions.
12:14 UTC
State is refreshed or the existing resource is adopted
Signal: The caller fetches current state, merges changes, or treats the already-created resource as success.
Why it matters: That confirms the root cause lived in stale state or duplicate intent, not generic transport failure.
Seen in Production
Parallel editors overwrite the same record
Frequency: common
Example: Two operators update one ticket; second update hits 409 because first write already changed version.
Fix: Force read-before-write refresh and require precondition headers or version fields on every mutation.
Duplicate create requests race across retry path
Frequency: common
Example: Client retries create without idempotency key and conflicts with unique external reference.
Fix: Make create operations idempotent and map duplicates to deterministic conflict responses.
Workflow transition conflicts with current business state
Frequency: medium
Example: Cancellation arrives after fulfillment started, and the service rejects the state change with 409.
Fix: Expose current workflow state and route callers to the correct transition path instead of forcing the original action.
Wrong Fix vs Better Fix
Retry same write vs refresh state first
Wrong fix: Replay the same mutation immediately after a 409.
Better fix: Fetch current state, inspect the conflict reason, and then recompute the mutation.
Why this is better: The original request was based on stale or conflicting assumptions, so resending it rarely helps.
Treat duplicate create as failure vs adopt existing success
Wrong fix: Create again with the same business identifier and hope the conflict clears.
Better fix: Use idempotency keys or duplicate-detection logic to adopt the already-created resource when appropriate.
Why this is better: Many 409s mean the desired state already exists once, not that the client should create it again.
Disable protections vs expose conflict detail
Wrong fix: Loosen uniqueness or version checks to reduce friction.
Better fix: Return machine-readable conflict reasons so callers can merge, refresh, or redirect safely.
Why this is better: 409 is often the system protecting correctness. Better conflict detail is safer than removing guards.
Debugging Tools
- -Workflow traces with correlation IDs
- -Version/ETag token inspection
- -Queue and orchestration execution logs
- -Concurrency diagnostics
How to Verify the Fix
- -Repeat the mutation and confirm 409 resolves when current preconditions are supplied or duplicate intent is handled idempotently.
- -Validate concurrency controls across normal, burst, and parallel writer scenarios.
- -Monitor conflict-rate metrics and ensure they drop to expected baseline after rollout.
- -Confirm duplicate create paths converge to one adopted resource instead of repeated collisions.
How to Prevent Recurrence
- -Adopt optimistic concurrency tokens and idempotency guards for mutating operations.
- -Serialize high-contention writes and enforce deterministic dependency ordering.
- -Monitor precondition and lock-related failure signals with actionable alerts.
- -Expose machine-readable conflict reasons such as
version_mismatch,duplicate_external_id, orinvalid_transitionso SDKs can choose the right recovery path.
Pro Tip
- -require clients to send explicit version or idempotency identity on every high-impact mutation so 409 paths remain predictable.
Decision Support
Compare Guide
409 Conflict vs 412 Precondition Failed: When to Use Each
Choose 412 when If-Match or If-Unmodified-Since checks fail; choose 409 for state conflicts without failed precondition headers during concurrent updates.
Playbook
Conflict and Concurrency Playbook (409 / 412 / OptimisticLock)
Use this playbook to separate true write conflicts from stale precondition failures, then apply safe re-fetch, optimistic-lock, and retry choices.
Official References
Provider Context
This guidance is specific to HTTP services. Always validate implementation details against official provider documentation before deploying to production.