quarkusio/quarkus · error · IOException

Stream is closed

Error message

Stream is closed

What it means

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.

Source

Thrown at independent-projects/resteasy-reactive/server/vertx/src/main/java/org/jboss/resteasy/reactive/server/vertx/VertxInputStream.java:81

    @Override
    public int read() throws IOException {
        byte[] b = new byte[1];
        int read = read(b);
        if (read == -1) {
            return -1;
        }
        return b[0] & 0xff;
    }

    @Override
    public int read(final byte[] b) throws IOException {
        return read(b, 0, b.length);
    }

    @Override
    public int read(final byte[] b, final int off, final int len) throws IOException {
        if (closed) {
            throw new IOException("Stream is closed");
        }
        if (vertxResteasyReactiveRequestContext.continueState == VertxResteasyReactiveRequestContext.ContinueState.REQUIRED) {
            vertxResteasyReactiveRequestContext.continueState = VertxResteasyReactiveRequestContext.ContinueState.SENT;
            vertxResteasyReactiveRequestContext.response.writeContinue();
        }
        readIntoBuffer();
        if (limit > 0 && exchange.request.bytesRead() > limit) {
            HttpServerResponse response = exchange.request.response();
            if (response.headWritten()) {
                //the response has been written, not much we can do
                exchange.request.connection().close();
                throw new IOException("Request too large");
            } else {
                response.setStatusCode(HttpResponseStatus.REQUEST_ENTITY_TOO_LARGE.code());
                response.headers().add(HttpHeaderNames.CONNECTION, "close");
                response.endHandler(new Handler<Void>() {
                    @Override
                    public void handle(Void event) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Read the request body exactly once; pass the already-read bytes along instead of re-reading the stream
  2. Do not call close() yourself before you finish reading; remove explicit close in filters/interceptors
  3. If the body must be consumed multiple times, buffer it (byte[]/BlockingInputStream) first
  4. Fix lifecycle bugs where the stream reference outlives its request (avoid storing request streams in singletons/fields)

Example fix

// before
String body = new String(in.readAllBytes());
in.close();
String again = new String(in.readAllBytes()); // IOException: Stream is closed

// after
byte[] data = in.readAllBytes();
in.close();
String body = new String(data);
String again = new String(data); // reuse buffer
Defensive patterns

Strategy: try-catch

Validate before calling

// read the body once and buffer it
byte[] buffered = inputStream.readAllBytes();
boolean streamUsable = !buffered.getClass().getName().isEmpty(); // reuse bytes, not the stream

Type guard

boolean isStreamOpen(InputStream in) {
    return !(in instanceof VertxInputStream vi) || !vi.isClosed();
}

Try / catch

try {
    return readBody(in);
} catch (IOException e) {
    if ("Stream is closed".equals(e.getMessage())) {
        throw new IllegalStateException("Request body already consumed; buffer it first", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/84e55b63e7cfd721. Report an issue: GitHub.