{"record":{"id":"84e55b63e7cfd721","repo":"quarkusio/quarkus","slug":"stream-is-closed-84e55b","errorCode":null,"errorMessage":"Stream is closed","messagePattern":"Stream is closed","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"independent-projects/resteasy-reactive/server/vertx/src/main/java/org/jboss/resteasy/reactive/server/vertx/VertxInputStream.java","lineNumber":81,"sourceCode":"    @Override\n    public int read() throws IOException {\n        byte[] b = new byte[1];\n        int read = read(b);\n        if (read == -1) {\n            return -1;\n        }\n        return b[0] & 0xff;\n    }\n\n    @Override\n    public int read(final byte[] b) throws IOException {\n        return read(b, 0, b.length);\n    }\n\n    @Override\n    public int read(final byte[] b, final int off, final int len) throws IOException {\n        if (closed) {\n            throw new IOException(\"Stream is closed\");\n        }\n        if (vertxResteasyReactiveRequestContext.continueState == VertxResteasyReactiveRequestContext.ContinueState.REQUIRED) {\n            vertxResteasyReactiveRequestContext.continueState = VertxResteasyReactiveRequestContext.ContinueState.SENT;\n            vertxResteasyReactiveRequestContext.response.writeContinue();\n        }\n        readIntoBuffer();\n        if (limit > 0 && exchange.request.bytesRead() > limit) {\n            HttpServerResponse response = exchange.request.response();\n            if (response.headWritten()) {\n                //the response has been written, not much we can do\n                exchange.request.connection().close();\n                throw new IOException(\"Request too large\");\n            } else {\n                response.setStatusCode(HttpResponseStatus.REQUEST_ENTITY_TOO_LARGE.code());\n                response.headers().add(HttpHeaderNames.CONNECTION, \"close\");\n                response.endHandler(new Handler<Void>() {\n                    @Override\n                    public void handle(Void event) {","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/resteasy-reactive/server/vertx/src/main/java/org/jboss/resteasy/reactive/server/vertx/VertxInputStream.java#L63-L99","documentation":"VertxInputStream.read throws this IOException when the request input stream has already been closed and read() is called again. It signals an attempt to consume the request body after the stream was finished/closed, which is not allowed.","triggerScenarios":"Calling read() on the request InputStream after close(), after the body was fully consumed, or after the framework closed the stream (e.g. in a filter after reading, or reading the body twice).","commonSituations":"Reading the request body in both a request filter and the resource method; caching/holding the InputStream across requests (e.g. storing it in a field); reading a body after the request completed (async continuation after close); double-invocation of interceptors.","solutions":["Read the request body exactly once; pass the already-read bytes along instead of re-reading the stream","Do not call close() yourself before you finish reading; remove explicit close in filters/interceptors","If the body must be consumed multiple times, buffer it (byte[]/BlockingInputStream) first","Fix lifecycle bugs where the stream reference outlives its request (avoid storing request streams in singletons/fields)"],"exampleFix":"// before\nString body = new String(in.readAllBytes());\nin.close();\nString again = new String(in.readAllBytes()); // IOException: Stream is closed\n\n// after\nbyte[] data = in.readAllBytes();\nin.close();\nString body = new String(data);\nString again = new String(data); // reuse buffer","handlingStrategy":"try-catch","validationCode":"// read the body once and buffer it\nbyte[] buffered = inputStream.readAllBytes();\nboolean streamUsable = !buffered.getClass().getName().isEmpty(); // reuse bytes, not the stream","typeGuard":"boolean isStreamOpen(InputStream in) {\n    return !(in instanceof VertxInputStream vi) || !vi.isClosed();\n}","tryCatchPattern":"try {\n    return readBody(in);\n} catch (IOException e) {\n    if (\"Stream is closed\".equals(e.getMessage())) {\n        throw new IllegalStateException(\"Request body already consumed; buffer it first\", e);\n    }\n    throw e;\n}","preventionTips":["Read the request body exactly once — buffer to byte[] if needed multiple times","Never store request InputStreams in fields/singletons or across requests","Remove manual close() calls in filters before the body is fully read","Pass already-read data through request context attributes instead of re-reading"],"tags":["io","stream-closed","request-body","lifecycle"],"backgroundTag":"stream-already-closed","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"}