{"record":{"id":"47ccb90f8f5147e1","repo":"eclipse-vertx/vert.x","slug":"409-conflict","errorCode":null,"errorMessage":"409 Conflict","messagePattern":"409 Conflict","errorType":"http","errorClass":null,"httpStatus":409,"severity":"error","filePath":"vertx-core/src/main/java/io/vertx/core/http/HttpResponseExpectation.java","lineNumber":195,"sourceCode":"  /**\n   * 406 Not Acceptable\n   */\n  HttpResponseExpectation SC_NOT_ACCEPTABLE = status(406);\n\n  /**\n   * 407 Proxy Authentication Required\n   */\n  HttpResponseExpectation SC_PROXY_AUTHENTICATION_REQUIRED = status(407);\n\n  /**\n   * 408 Request Timeout\n   */\n  HttpResponseExpectation SC_REQUEST_TIMEOUT = status(408);\n\n  /**\n   * 409 Conflict\n   */\n  HttpResponseExpectation SC_CONFLICT = status(409);\n\n  /**\n   * 410 Gone\n   */\n  HttpResponseExpectation SC_GONE = status(410);\n\n  /**\n   * 411 Length Required\n   */\n  HttpResponseExpectation SC_LENGTH_REQUIRED = status(411);\n\n  /**\n   * 412 Precondition Failed\n   */\n  HttpResponseExpectation SC_PRECONDITION_FAILED = status(412);\n\n  /**\n   * 413 Request Entity Too Large","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/eclipse-vertx/vert.x/blob/fb308bd8c3f12c79f4ae89bef67fadf6c80d036e/vertx-core/src/main/java/io/vertx/core/http/HttpResponseExpectation.java#L177-L213","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nwebClient.put(path).putHeader(\"If-Match\", staleEtag).sendJson(body); // 409\n// after\nwebClient.get(path).send()\n  .onSuccess(get -> {\n    String etag = get.getHeader(\"ETag\");\n    webClient.put(path).putHeader(\"If-Match\", etag).sendJson(body);\n  });","handlingStrategy":"validation","validationCode":"// Before PUT/PATCH, re-check the current state\nJsonObject current = awaitGet(path);\nif (!current.getJsonObject(\"state\").equals(expectedState)) { rebaseChange(); }","typeGuard":"boolean isConflict(Throwable t) {\n  return t instanceof VertxHttpResponseException\n    && ((VertxHttpResponseException) t).getResponse().statusCode() == 409;\n}","tryCatchPattern":"if (isConflict(t)) { refetchAndRebase(); } else { throw t; }","preventionTips":["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"],"tags":["http","conflict","state","vertx"],"backgroundTag":"http-error-response","analyzedSha":"fb308bd8c3f12c79f4ae89bef67fadf6c80d036e","analyzedAt":"2026-09-06T11:37:12.241Z","contentChangedAt":"2026-09-06T11:37:12.241Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}