quarkusio/quarkus · error · IllegalStateException

Response has been closed

Error message

Response has been closed

What it means

RestResponseImpl.checkClosed throws IllegalStateException when any entity-related method is invoked after the response has been closed, unless the response was buffered. The JAX-RS Response lifecycle forbids access to the entity stream after close(); buffered responses keep their data in memory and are exempt per the TCK.

Source

Thrown at independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/jaxrs/RestResponseImpl.java:210

                    while ((read = entityStream.read(buffer)) != -1) {
                        os.write(buffer, 0, read);
                    }
                    entityStream.close();
                } catch (IOException x) {
                    throw new UncheckedIOException(x);
                }
                entityStream = new ByteArrayInputStream(os.toByteArray());
            }
            buffered = true;
            return true;
        }
        return false;
    }

    protected void checkClosed() {
        // apparently the TCK says that buffered responses don't care about being closed
        if (closed && !buffered)
            throw new IllegalStateException("Response has been closed");
    }

    @Override
    public void close() {
        if (!closed) {
            closed = true;
            if (entityStream != null) {
                try {
                    entityStream.close();
                } catch (IOException e) {
                    throw new ProcessingException(e);
                }
            }
        }
    }

    @Override
    public MediaType getMediaType() {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Call bufferEntity() before close() if you need the entity afterwards
  2. Move all entity reads inside the try-with-resources block, before close()
  3. Do not close the response until entity processing is complete
  4. Restructure to consume the entity immediately when the response is received

Example fix

// before
try (RestResponse<Foo> r = client.call()) {
    // no read here
}
Foo f = r.readEntity(Foo.class); // IllegalStateException
// after
Foo f;
try (RestResponse<Foo> r = client.call()) {
    f = r.readEntity(Foo.class);
}
Defensive patterns

Strategy: validation

Validate before calling

if (response.isClosed() && !response.isBuffered()) {
    throw new IllegalStateException("Refusing to read from closed response");
}

Type guard

boolean usable(RestResponse<?> r) {
    return r != null && (!r.isClosed() || r.isBuffered());
}

Try / catch

try {
    return response.readEntity(String.class);
} catch (IllegalStateException e) {
    log.warn("Response already closed");
    return null;
}

Prevention

When it happens

Trigger: Calling getEntity(), readEntity(), hasEntity(), or bufferEntity() after close() has been called on a non-buffered RestResponse; using try-with-resources on a response and then reading the entity outside the block; response auto-closed by a framework/interceptor before your read.

Common situations: try-with-resources pattern where readEntity happens after the resource block; leaking a response across async boundaries after it was closed; reading the entity in a finally or later callback after close.

Related errors


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