{"record":{"id":"f76103cb5688e69e","repo":"quarkusio/quarkus","slug":"response-already-committed","errorCode":null,"errorMessage":"Response already committed","messagePattern":"Response already committed","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/resteasy-classic/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxHttpResponse.java","lineNumber":115,"sourceCode":"        }\n        response.setStatusCode(status);\n        if (message != null) {\n            response.end(message);\n        } else {\n            response.end();\n        }\n        committed = true;\n    }\n\n    @Override\n    public boolean isCommitted() {\n        return committed;\n    }\n\n    @Override\n    public void reset() {\n        if (committed) {\n            throw new IllegalStateException(\"Response already committed\");\n        }\n        outputHeaders.clear();\n    }\n\n    private void transformHeaders() {\n        getOutputHeaders().forEach(this::transformHeadersList);\n    }\n\n    private void transformHeadersList(final String key, final List<Object> valueList) {\n        final MultiMap headers = response.headers();\n        for (Object value : valueList) {\n            if (value == null) {\n                headers.add(key, \"\");\n            } else {\n                RuntimeDelegate.HeaderDelegate delegate = providerFactory.getHeaderDelegate(value.getClass());\n                if (delegate != null) {\n                    headers.add(key, delegate.toString(value));\n                } else {","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/resteasy-classic/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxHttpResponse.java#L97-L133","documentation":"VertxHttpResponse.reset() implements the servlet-style reset contract: once the response is committed (headers/status already sent to the wire), it cannot be reset. It throws IllegalStateException(\"Response already committed\") to prevent mutating headers of a response the client has already started receiving.","triggerScenarios":"Calling response.reset() (directly or via getOutputStream side effects / container machinery) after the response was flushed or its headers written; e.g. an exception handler trying to reset the response to send a different status after partial output was committed.","commonSituations":"Custom error handling that attempts to change the status code after output started; exception mappers firing after the entity stream was flushed; frameworks that reset responses defensively in finally blocks.","solutions":["Only reset before writing any entity/status — restructure error handling so failures are detected before the first write/flush.","Instead of reset after commit, log the issue and close the stream; the client already received the committed response.","Use flush() deliberately and late: avoid premature flushing in mappers/interceptors so reset remains possible for error paths."],"exampleFix":"// before\ntry {\n    out.write(data);\n} catch (Exception e) {\n    response.reset(); // IllegalStateException: already committed\n    response.setStatusCode(500);\n}\n\n// after\nboolean ok = renderData(out); // validate/build first, write last\nif (!ok) {\n    response.setStatusCode(500); // nothing written yet, safe\n}","handlingStrategy":"validation","validationCode":"if (response.isCommitted()) {\n    throw new IllegalStateException(\"Cannot reset: response already committed\");\n}\nresponse.reset();","typeGuard":"boolean safeToReset(io.quarkus.resteasy.runtime.standalone.VertxHttpResponse resp) {\n    return !resp.isCommitted();\n}","tryCatchPattern":"try {\n    response.reset();\n} catch (IllegalStateException e) {\n    LOG.warn(\"Response already committed; cannot reset — client received partial response\");\n}","preventionTips":["Validate inputs and resolve errors before writing any entity or headers.","Avoid flushing early in interceptors/mappers so the response stays resettable.","Never call reset() from finally blocks.","Use exception mappers that run before output starts (handle exceptions before first write)."],"tags":["http","response","illegal-state","vertx"],"backgroundTag":"response-already-committed","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}