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

  1. Fetch the current resource and ETag, re-apply your change, and resend with an up-to-date If-Match header
  2. Check for existence before create (or use an upsert-style endpoint) when 409 means duplicate
  3. On retry, make the operation idempotent (deterministic IDs, idempotency keys)
  4. Inspect the response body: most APIs detail which constraint conflicted
  5. 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

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


AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06). Data as JSON: /api/errors/47ccb90f8f5147e1. Report an issue: GitHub.