A 409 error means the server hit a conflict with the resource’s current state, so your update can’t be applied until you sync or change the request.
A 409 response usually shows up when two actions collide. You submit an update, the server understands it, yet the stored version has shifted since your app last fetched it. That mismatch is the whole story: state on your side and state on the server don’t line up.
This article shows you what that conflict looks like in real systems, how to pinpoint the exact request that caused it, and what to change so it stops repeating. You’ll see quick checks for browsers, WordPress, REST APIs, and automation scripts.
409 Errors In Plain Terms
HTTP status code 409 is named “Conflict.” The HTTP spec describes it as a request that can’t be completed because it conflicts with the current state of the target resource. Servers are also expected to return enough detail for a person to spot what collided and try again with the right state.
In day-to-day work, “conflict” usually means one of these:
- Stale data update — Your client sends an older version of a record and tries to overwrite a newer one.
- Duplicate creation — Your client tries to create a resource that already exists under rules that require uniqueness.
- Out-of-order workflow — You trigger step 3 while the server is still at step 2, so the transition is rejected.
- Concurrent writes — Two writers try to change the same item at the same time, and one loses.
Browsers often surface the error as a plain “409 Conflict” page. APIs often return JSON that points at a field, a version number, or a lock token. Either way, the fix is rarely “try later” with no other change. You usually need to re-fetch current state, then resend with updated preconditions.
What Commonly Triggers 409 errors
You can spot patterns once you group triggers by what is colliding: versions, uniqueness rules, or timing. Start with the trigger that matches your setup.
Concurrent edits in apps
Two people edit the same record, or two browser tabs submit changes seconds apart. The second update arrives with an older “last updated” value and gets blocked. Many apps use a version column, a timestamp, or an ETag value to detect this case.
Conflicts during create operations
Some APIs choose 409 when a POST tries to create an item that already exists. This can happen with usernames, slugs, invoice numbers, or any unique index. It also happens when a previous request succeeded but the client never got the response, then repeats the call and “creates” again.
Version control and file APIs
Services that store files often require a current revision identifier on update. Git-based APIs are a classic example: if you update a file without the latest SHA or revision id, the service returns a conflict so you don’t overwrite someone else’s commit.
Locks and busy resources
Some servers represent an active lock as a conflict. You might see this when a deployment is running, when a job already holds a solo lock, or when a document is checked out.
Troubleshooting 409 Errors Step By Step
The fastest route to a clean fix is to identify the exact request that got the 409, then compare what you sent with what the server expected at that moment.
- Reproduce the action once — Trigger the problem with one controlled attempt so logs stay readable.
- Capture the failing request — In a browser, open DevTools → Network, repeat the action, then click the request with status 409.
- Read the response body — Many APIs include a message like “version mismatch,” “resource exists,” or “lock held,” plus a field name.
- Compare versions — Look for ETag/If-Match, a version number in JSON, a revision header, or a timestamp your client sent.
- Check server logs for the same trace — Match by request id, path, time, or correlation id, then read the server-side reason.
- Confirm idempotency — For create or payment-like actions, check if your client can repeat safely or if it needs an idempotency token.
If you can, replay the request with curl or a REST client. It strips away UI noise and shows headers in one place. Save the raw request, then change one thing at a time: body, headers, or sequence. When the 409 disappears, you’ve found the trigger right now.
If you only have the status code with no body, add structured error output on the server. A common format is RFC 9457 “problem details” JSON, which most modern stacks can emit with a title, status, and a human-readable detail.
Fixing Conflict Responses In WordPress And APIs
Fixes fall into a handful of repeatable moves. Pick the one that matches your trigger, then validate with a second run of the same request.
Browser-side quick resets
- Hard reload the page — Force a fresh fetch so you aren’t submitting old cached form data.
- Clear site data for one domain — Remove cookies and local storage for the site, then sign in again and retry.
- Try a single clean tab — Close duplicate tabs that can submit the same action twice.
WordPress admin and plugin conflicts
On WordPress, 409 responses often come from a plugin, a security layer, or an API call made by the editor. You want to isolate what is generating the request.
- Disable one plugin at a time — Pause caching, security, and editor add-ons first, then retry the same action.
- Switch to a default theme — Rule out theme-side scripts that send duplicate updates.
- Check WAF and CDN logs — A firewall rule can block or rewrite requests in a way that creates conflicts.
REST API update conflicts
When an update fails due to stale data, the safest fix is “read, merge, write.” Fetch the latest state, apply your changes on top of it, then submit the update with a fresh version token.
- Fetch current state first — GET the resource right before the update so you have the latest version.
- Send If-Match with ETag — Use the ETag from the GET in your update precondition so the server can detect stale overwrites.
- Handle merge on conflict — If the server returns 409, re-fetch, merge fields, and resubmit once.
Duplicate create and replay fixes
- Use an idempotency token — Attach a stable request id so a retry returns the first result instead of creating again.
- Choose PUT for client-chosen ids — If the client picks the id, PUT to that URL can avoid duplicate POST creates.
- Return a resource link on conflict — When a create collides, return the existing resource identifier so the client can move on.
File and Git-style revision checks
- Read the latest revision — Fetch the current SHA or revision value before writing.
- Resend with the revision field — Include the revision in the update body so the server can verify you’re updating what you read.
- Retry after a short backoff — For high-write repos, a brief delay can reduce collisions between automated commits.
Prevention Patterns That Stop Repeat Conflicts
Once you have one clean fix, lock in a pattern so 409 errors don’t keep coming back during peak usage or during retries.
Use preconditions for updates
ETags plus If-Match give you a simple safety rail. They tell the server “apply this only if the resource still matches the version I saw.” When it doesn’t match, you get a conflict instead of a silent overwrite.
Make retries safe
Retries can create new conflicts if they repeat a non-idempotent action. Idempotency tokens for POST, plus clear retry rules for PUT and PATCH, reduce duplicate creates and double-charges.
Serialize writes when needed
If a single record gets hammered by concurrent writers, you may need short-lived locks, a queue, or a “single writer” job that applies changes in order. This is more work, yet it can be the right move for inventory, billing, or rate-limited third-party APIs.
Return conflict details people can act on
The HTTP spec recommends returning enough detail for a person to recognize the source of the conflict. In practice, add a machine-readable error code, a short message, and a pointer to the field or version that failed. It saves hours during debugging and reduces blind retries.
Choosing 409 Vs Nearby Status Codes
409 is one tool in the 4xx set. Picking the right code makes clients behave better and keeps logs easier to triage.
| Code | When It Fits | What The Client Should Do |
|---|---|---|
| 409 | State conflict on the target resource | Re-fetch state, then resend with fresh version or new data |
| 412 | Precondition check failed (If-Match, If-Unmodified-Since) | Get a new ETag or timestamp, then retry with updated precondition |
| 422 | Well-formed request, but semantic validation failed | Fix payload fields, then resubmit without changing resource version |
Clients often treat 412 as “my precondition was wrong” and 409 as “the resource is in a conflicting state.” Some APIs use 409 for both cases. Consistency across your own endpoints matters more than copying a single pattern from a random API.
If you want a single mental model, use this: 409 means “your action collides with the current state,” while 422 means “your data doesn’t pass rules,” and 412 means “the conditional header check failed.”
When you’re writing client code, treat 409 errors as a signal to refresh state and attempt a controlled retry once. If it fails again, surface the conflict to the user with the server’s detail so they can decide what to keep.
409 Conflict checklist for a clean rerun
When you hit the same conflict twice, slow down and validate the basics. A second failure usually means you’re retrying the same stale request, not the right request.
- Confirm the method — Make sure the client isn’t sending POST when your design expects PUT or PATCH for updates.
- Verify the resource id — Check that the URL points at the item you just fetched, not an older cached id.
- Refresh the version token — Re-run the GET, store the new ETag or version value, then use it in the next update.
- Remove accidental duplicates — Look for double submit handlers, retries in a fetch wrapper, or two workers acting on the same queue item.
- Log the winning state — Print the server’s current version and your client’s version side by side so the mismatch is obvious.
If you’re building the server side, add a short, stable error code like conflict_version or conflict_exists. It lets clients branch cleanly without parsing text. Pair it with a field pointer and the latest version value when it’s safe to return it.
For reference, these official pages define the status code and its intent: MDN on 409 Conflict, RFC 9110 HTTP Semantics, and the IANA HTTP Status Code Registry.
