quarkusio/quarkus · error · java.lang.UnsupportedOperationException

`jakarta.ws.rs.ext.ExceptionMapper` are not supported in RES

Error message

`jakarta.ws.rs.ext.ExceptionMapper` are not supported in REST Client Reactive

What it means

REST Client Reactive throws this UnsupportedOperationException because jakarta.ws.rs.ext.ExceptionMapper does not fit the reactive client's execution model: response errors are surfaced as failures on the returned Uni/Multi rather than routed through mapper beans. ProvidersImpl therefore rejects getExceptionMapper outright.

Source

Thrown at independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/ProvidersImpl.java:51

        return null;
    }

    @Override
    public <T> MessageBodyWriter<T> getMessageBodyWriter(Class<T> type, Type genericType, Annotation[] annotations,
            MediaType mediaType) {
        List<MessageBodyWriter<?>> writers = context.getRestClient().getClientContext().getSerialisers()
                .findWriters(context.getConfiguration(), type, mediaType, RuntimeType.CLIENT);
        for (MessageBodyWriter<?> writer : writers) {
            if (writer.isWriteable(type, genericType, annotations, mediaType)) {
                return (MessageBodyWriter<T>) writer;
            }
        }
        return null;
    }

    @Override
    public <T extends Throwable> ExceptionMapper<T> getExceptionMapper(Class<T> type) {
        throw new UnsupportedOperationException(
                "`jakarta.ws.rs.ext.ExceptionMapper` are not supported in REST Client Reactive");
    }

    @Override
    public <T> ContextResolver<T> getContextResolver(Class<T> contextType, MediaType mediaType) {
        // TODO: support getting context resolver by mediaType (which is provided using the `@Produces` annotation).
        return context.getConfiguration().getContextResolver(contextType);
    }
}

View on GitHub (pinned to e1c734241f)

Solutions

  1. Handle errors on the Uni/Multi returned by the client with .onFailure().recoverWith... instead of an ExceptionMapper
  2. Remove the getExceptionMapper call and process Response/Throwable in a ClientResponseFilter or in the subscription's onFailure callback
  3. If shared code needs a mapper, feature-detect with try/catch around UnsupportedOperationException

Example fix

// before
ExceptionMapper<FooException> m = providers.getExceptionMapper(FooException.class);
// after
uni.onFailure(FooException.class, ex -> mapIt(ex)).subscribe().with(...)
Defensive patterns

Strategy: try-catch

Validate before calling

ExceptionMapper<?> mapper = null;
try {
    mapper = providers.getExceptionMapper(type);
} catch (UnsupportedOperationException ignored) {
    // reactive client: handle via Uni/Multi onFailure instead
}

Type guard

boolean supportsExceptionMappers(Providers p) {
    return !(p instanceof org.jboss.resteasy.reactive.client.impl.ProvidersImpl);
}

Try / catch

try {
    return providers.getExceptionMapper(type);
} catch (UnsupportedOperationException e) {
    log.warn("ExceptionMapper unsupported in REST Client Reactive; use onFailure on Uni/Multi");
    return null;
}

Prevention

When it happens

Trigger: Calling providers.getExceptionMapper(SomeException.class) on the client's Providers instance — usually from a ReaderInterceptor, WriterInterceptor, or custom message body worker that resolves via ContextProviders/ProvidersImpl.exceptionMapper().

Common situations: Migrating a server-side provider or a classic RESTEasy client interceptor to the reactive client and expecting ExceptionMapper support; shared library code that calls getExceptionMapper unconditionally.

Related errors


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