quarkusio/quarkus · error · IllegalStateException

getContent() has already been invoked

Error message

getContent() has already been invoked

What it means

EntityPartImpl.getContent() (the InputStream overload) throws IllegalStateException if called more than once. An EntityPart's body is a one-shot stream; once consumed it cannot be rewound, so the implementation guards with a compareAndSet flag and fails fast on the second call. This mirrors the JAX-RS 3.1 spec's single-consumption semantics.

Source

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

        this.mediaType = mediaType;
        this.content = content;
        this.serialisers = serialisers;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public Optional<String> getFileName() {
        return Optional.ofNullable(fileName);
    }

    @Override
    public InputStream getContent() {
        if (!contentConsumed.compareAndSet(false, true)) {
            throw new IllegalStateException("getContent() has already been invoked");
        }
        return content;
    }

    @Override
    public <T> T getContent(Class<T> type)
            throws IllegalArgumentException, IllegalStateException, IOException, WebApplicationException {
        if (!contentConsumed.compareAndSet(false, true)) {
            throw new IllegalStateException("getContent() has already been invoked");
        }
        return readContent(type, type);
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> T getContent(GenericType<T> type)
            throws IllegalArgumentException, IllegalStateException, IOException, WebApplicationException {
        if (!contentConsumed.compareAndSet(false, true)) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Call getContent() exactly once and buffer the bytes (read all into byte[]) if you need multiple uses.
  2. Use one of the typed overloads getContent(Class) / getContent(GenericType) instead of multiple raw reads.
  3. Cache the converted value (e.g. String or byte[]) in a local variable and reuse it.

Example fix

// before
String logged = new String(part.getContent().readAllBytes());
process(part.getContent()); // IllegalStateException: already invoked
// after
byte[] data = part.getContent().readAllBytes();
String logged = new String(data);
process(new ByteArrayInputStream(data));
Defensive patterns

Strategy: try-catch

Try / catch

try {
    InputStream in = part.getContent();
    byte[] data = in.readAllBytes(); // consume once, reuse everywhere
} catch (IllegalStateException e) {
    if (e.getMessage().contains("already been invoked")) {
        throw new IllegalStateException("part content read twice; buffer instead", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling part.getContent() twice on the same EntityPart obtained from a MultipartFormDataOutput response or client parse — e.g. reading the raw stream and then, in error handling or logging, reading it again.

Common situations: Logging part content then passing it downstream; retry/error paths that re-read the same part; interceptors or filters that consume the content before the business code does.

Related errors


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