quarkusio/quarkus · error · IllegalArgumentException
Failed to instantiate provider " + componentClass + ". Does
Error message
Failed to instantiate provider " + componentClass + ". Does it have a public no-arg constructor?
What it means
When registering a provider class, registerMpSpecificProvider instantiates MP-specific providers (ResponseExceptionMapper and ParamConverterProvider implementations) via their public no-arg constructor. If instantiation fails (abstract class, missing constructor, inaccessible constructor, throwing constructor), it wraps the reflective exception in this IllegalArgumentException. Non-MP providers (filters, interceptors) are instantiated elsewhere and do not hit this path.
Source
Thrown at extensions/resteasy-reactive/rest-client/runtime/src/main/java/io/quarkus/rest/client/reactive/runtime/RestClientBuilderImpl.java:470
public RestClientBuilderImpl register(Object component, Map<Class<?>, Integer> contracts) {
registerMpSpecificProvider(component);
clientBuilder.register(component, contracts);
return this;
}
@Override
public RestClientBuilderImpl baseUri(URI uri) {
this.uri = uri;
return this;
}
private void registerMpSpecificProvider(Class<?> componentClass) {
if (ResponseExceptionMapper.class.isAssignableFrom(componentClass)
|| ParamConverterProvider.class.isAssignableFrom(componentClass)) {
try {
registerMpSpecificProvider(componentClass.getDeclaredConstructor().newInstance());
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
throw new IllegalArgumentException("Failed to instantiate provider " + componentClass
+ ". Does it have a public no-arg constructor?", e);
}
}
}
private void registerMpSpecificProvider(Object component) {
if (component instanceof ResponseExceptionMapper) {
exceptionMappers.add((ResponseExceptionMapper<?>) component);
}
if (component instanceof ParamConverterProvider) {
paramConverterProviders.add((ParamConverterProvider) component);
}
}
@Override
public RestClientBuilderImpl queryParamStyle(final QueryParamStyle style) {
queryParamStyle = style;
return this;View on GitHub (pinned to e1c734241f)
Solutions
- Add a public no-argument constructor to the provider class (or make the existing constructor public).
- Register an instance instead of a class: builder.register(new MyMapper(...)) or use @RegisterProvider / CDI-managed registration for annotation-registered providers.
- Ensure the class is concrete (not abstract or an interface).
Example fix
// before
public class MyMapper implements ResponseExceptionMapper {
public MyMapper(String config) { ... } // no no-arg ctor
}
// after
public class MyMapper implements ResponseExceptionMapper {
public MyMapper() { ... }
} Defensive patterns
Strategy: validation
Validate before calling
Class<?> c = MyMapper.class;
boolean ok = !java.lang.reflect.Modifier.isAbstract(c.getModifiers());
try { c.getDeclaredConstructor().newInstance(); } catch (Exception e) { /* fail fast before register */ } Type guard
boolean instantiableProvider(Class<?> c) {
return !c.isInterface() && !java.lang.reflect.Modifier.isAbstract(c.getModifiers())
&& java.util.Arrays.stream(c.getDeclaredConstructors())
.anyMatch(k -> k.getParameterCount() == 0 && java.lang.reflect.Modifier.isPublic(k.getModifiers()));
} Try / catch
try {
builder.register(MyMapper.class);
} catch (IllegalArgumentException e) {
builder.register(new MyMapper(dep)); // instance fallback
} Prevention
- Always give ResponseExceptionMapper/ParamConverterProvider classes a public no-arg constructor.
- Register by instance when constructor injection is required.
- Unit-test provider registration in a plain builder before app startup.
When it happens
Trigger: builder.register(MyResponseExceptionMapper.class) or register(MyParamConverterProvider.class) where that class lacks a public no-arg constructor, is abstract, or its constructor throws.
Common situations: Registering a mapper class that requires constructor injection (e.g. takes a config parameter); registering an abstract base mapper class by mistake; CDI users forgetting that class-based registration here means reflective instantiation, not CDI creation.
Related errors
- Couldn't extract all parameters information for constructor
- Failed to set dev services config
- Failed to set dev services override config
- Unable to find or load top command: <className>
- Unable to find the following conversion class: ${customConve
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/35bbd01acecff01f.
Report an issue: GitHub.