quarkusio/quarkus · error · UnsupportedOperationException

Returning an AsyncFile is not supported with WriterIntercept

Error message

Returning an AsyncFile is not supported with WriterInterceptors

What it means

ServerMutinyAsyncFileMessageBodyWriter.writeTo() unconditionally throws UnsupportedOperationException: returning a Vert.x AsyncFile as a Jakarta REST entity is only supported when it can be written directly (no WriterInterceptors apply). When WriterInterceptors are present, the writer must use the entity OutputStream, which AsyncFile streaming cannot support, so it fails fast.

Source

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

        });

        file.endHandler(new Runnable() {
            @Override
            public void run() {
                // we don't need to wait for the file to be closed, we just need to make sure it does get closed
                //noinspection ResultOfMethodCallIgnored
                file.close().subscribeAsCompletionStage();
                response.end();
                // Not sure if I need to resume, actually
                ctx.resume();
            }
        });
    }

    @Override
    public void writeTo(AsyncFile asyncFile, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
            MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {
        throw new UnsupportedOperationException("Returning an AsyncFile is not supported with WriterInterceptors");
    }
}

View on GitHub (pinned to e1c734241f)

Solutions

  1. Remove or disable the WriterInterceptor for AsyncFile responses (target it to other types via @InterceptorBinding/accepted media types).
  2. Return the file content differently: InputStream/File/StreamingOutput instead of AsyncFile when interceptors are needed.
  3. Write the file bytes into the provided OutputStream manually inside the endpoint if interceptor processing is required.

Example fix

// before
@GET public AsyncFile download() { return fileSystem.open(...); } // with WriterInterceptor -> throws
// after
@GET public File download() { return new File(path); } // interceptor-compatible
Defensive patterns

Strategy: validation

Validate before calling

// before returning AsyncFile, check no writer interceptors will apply
boolean hasWriterInterceptors = !interceptorRegistry.getWriterInterceptors(asyncFileType, mediaType).isEmpty();
if (hasWriterInterceptors) return toFileOrInputStream(asyncFile);

Type guard

boolean canReturnAsyncFile(Object entity, boolean writerInterceptorsPresent) {
    return entity instanceof io.vertx.mutiny.core.file.AsyncFile && !writerInterceptorsPresent;
}

Try / catch

try {
    return asyncFile;
} catch (UnsupportedOperationException e) {
    if (e.getMessage().contains("AsyncFile is not supported")) {
        return readFileAsInputStream(path); // fallback
    }
    throw e;
}

Prevention

When it happens

Trigger: A Jakarta REST resource method returns a Vert.x AsyncFile (or Mutiny AsyncFile) entity while WriterInterceptors are registered (e.g. custom @WriterInterceptor, some compression/ logging interceptors), causing the interceptor-aware writeTo path to be used.

Common situations: Serving files via AsyncFile after adding a writer interceptor (e.g. for logging or encryption); upgrading Quarkus where interceptors newly apply to the AsyncFile writer path.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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