eclipse-vertx/vert.x · error
409 Conflict
Error message
409 Conflict
What it means
SC_CONFLICT is the HttpResponseExpectation constant for HTTP 409 Conflict. Vert.x exposes it so applications can validate or reject responses; when the server responds 409 and this expectation is applied, validation fails with '409 Conflict'. 409 signals the request could not be completed because it conflicts with the current state of the target resource (e.g. version/etag mismatch, duplicate unique key).
Source
Thrown at vertx-core/src/main/java/io/vertx/core/http/HttpResponseExpectation.java:195
/** * 406 Not Acceptable */ HttpResponseExpectation SC_NOT_ACCEPTABLE = status(406); /** * 407 Proxy Authentication Required */ HttpResponseExpectation SC_PROXY_AUTHENTICATION_REQUIRED = status(407); /** * 408 Request Timeout */ HttpResponseExpectation SC_REQUEST_TIMEOUT = status(408); /** * 409 Conflict */ HttpResponseExpectation SC_CONFLICT = status(409); /** * 410 Gone */ HttpResponseExpectation SC_GONE = status(410); /** * 411 Length Required */ HttpResponseExpectation SC_LENGTH_REQUIRED = status(411); /** * 412 Precondition Failed */ HttpResponseExpectation SC_PRECONDITION_FAILED = status(412); /** * 413 Request Entity Too Large
View on GitHub (pinned to fb308bd8c3)
Solutions
- Fetch the current resource and ETag, re-apply your change, and resend with an up-to-date If-Match header
- Check for existence before create (or use an upsert-style endpoint) when 409 means duplicate
- On retry, make the operation idempotent (deterministic IDs, idempotency keys)
- Inspect the response body: most APIs detail which constraint conflicted
- Coordinate concurrent writers with locking or a queue if conflicts are frequent
Example fix
// before
webClient.put(path).putHeader("If-Match", staleEtag).sendJson(body); // 409
// after
webClient.get(path).send()
.onSuccess(get -> {
String etag = get.getHeader("ETag");
webClient.put(path).putHeader("If-Match", etag).sendJson(body);
}); Defensive patterns
Strategy: validation
Validate before calling
// Before PUT/PATCH, re-check the current state
JsonObject current = awaitGet(path);
if (!current.getJsonObject("state").equals(expectedState)) { rebaseChange(); } Type guard
boolean isConflict(Throwable t) {
return t instanceof VertxHttpResponseException
&& ((VertxHttpResponseException) t).getResponse().statusCode() == 409;
} Try / catch
if (isConflict(t)) { refetchAndRebase(); } else { throw t; } Prevention
- Always send a current If-Match ETag for state-changing calls
- Make create operations idempotent with deterministic IDs
- Check existence before create, or use upsert endpoints
- Read the 409 response body to learn the exact conflicting constraint
When it happens
Trigger: Performing a PUT/POST/PATCH via Vert.x WebClient against a resource whose current state conflicts: stale ETag/If-Match header, creating a resource that already exists with a unique constraint, or concurrent modification by another writer.
Common situations: Optimistic-locking workflows where another client updated the entity first, idempotency violations on retries (retrying a create that already succeeded), database unique-index violations surfaced as 409 by the API layer.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- only '\n' is allowed after '\r': <seq>
- only ' ' and '\t' are allowed after '\n': <seq>
- Request has already been read
- 408 Request Timeout
- 410 Gone
AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06).
Data as JSON: /api/errors/47ccb90f8f5147e1.
Report an issue: GitHub.