{"record":{"id":"9e51fff68291e54d","repo":"eclipse-vertx/vert.x","slug":"request-already-complete","errorCode":null,"errorMessage":"Request already complete","messagePattern":"Request already complete","errorType":"validation","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"vertx-core/src/main/java/io/vertx/core/http/impl/HttpClientRequestImpl.java","lineNumber":606,"sourceCode":"        uri = \"/\";\n      }\n      HttpRequestHead head = new HttpRequestHead(ssl ? \"https\" : \"http\", method, uri, headers, authority(), absoluteURI(), traceOperation);\n      future = stream.writeHead(head, chunked, buff, writeEnd, priority, connect);\n    } else {\n      if (buff == null && !end) {\n        throw new IllegalArgumentException();\n      }\n      future = stream.writeChunk(buff, writeEnd);\n    }\n    if (end) {\n      tryComplete();\n    }\n    return future;\n  }\n\n  private void checkEnded() {\n    if (trailersSent) {\n      throw new IllegalStateException(\"Request already complete\");\n    }\n  }\n\n  @Override\n  public synchronized HttpClientRequest setStreamPriority(StreamPriority priority) {\n    if (headersSent) {\n      stream.updatePriority(priority);\n    } else {\n      this.priority = priority;\n    }\n    return this;\n  }\n\n  @Override\n  public synchronized StreamPriority getStreamPriority() {\n    return stream.priority();\n  }\n}","sourceCodeStart":588,"sourceCodeEnd":624,"githubUrl":"https://github.com/eclipse-vertx/vert.x/blob/fb308bd8c3f12c79f4ae89bef67fadf6c80d036e/vertx-core/src/main/java/io/vertx/core/http/impl/HttpClientRequestImpl.java#L588-L624","documentation":"checkEnded() throws this IllegalStateException whenever an operation that writes or mutates the request (e.g. setStreamPriority) is invoked after the request has already been completed (trailers sent). Once the request is fully sent, its state can no longer change.","triggerScenarios":"Calling setStreamPriority, write, putHeader or similar after end()/end(chunk) has completed, e.g. asynchronously after a delayed callback fires post-completion.","commonSituations":"Async code that configures the request after awaiting something, while the request already ended due to an error path or early completion; duplicated completion paths calling end twice.","solutions":["Reorder code so priority/headers are set before end() is called","Track request completion (e.g. a boolean or the end future) and skip further mutations once ended","Only call end() once, from a single code path"],"exampleFix":"// before\nrequest.end();\nrequest.setStreamPriority(priority); // throws\n// after\nrequest.setStreamPriority(priority);\nrequest.end();","handlingStrategy":"type-guard","validationCode":"boolean ended = endFuture.isComplete();\nif (!ended) { request.setStreamPriority(priority); }","typeGuard":"void safeSetPriority(HttpClientRequest req, StreamPriority p, Future<Void> endFuture) {\n  if (!endFuture.isComplete()) req.setStreamPriority(p);\n}","tryCatchPattern":"try {\n  request.setStreamPriority(priority);\n} catch (IllegalStateException e) {\n  // request already complete; ignore or log\n}","preventionTips":["Set priority/headers before calling end()","Call end() from exactly one code path","Track completion with the future returned by end()"],"tags":["http-client","state","lifecycle"],"backgroundTag":"invalid-state-transition","analyzedSha":"fb308bd8c3f12c79f4ae89bef67fadf6c80d036e","analyzedAt":"2026-09-06T11:37:12.241Z","contentChangedAt":"2026-09-06T11:37:12.241Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}