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
- Remove or disable the WriterInterceptor for AsyncFile responses (target it to other types via @InterceptorBinding/accepted media types).
- Return the file content differently: InputStream/File/StreamingOutput instead of AsyncFile when interceptors are needed.
- 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
- Check registered WriterInterceptors before returning AsyncFile entities.
- Scope interceptors to specific types/media types so they don't hit AsyncFile.
- Prefer File/InputStream/StreamingOutput entities when interceptors are needed.
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
- Extra steps left over
- Unsupported value type: %s
- Unable to fully read json value
- Unknown start character for json value: %s
- Json object ended without }
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/e4d2011ef887a1b5.
Report an issue: GitHub.