quarkusio/quarkus · error · IllegalArgumentException
Class '{biFunctionClassInfo.name}' must contain a no-args co
Error message
Class '{biFunctionClassInfo.name}' must contain a no-args constructor What it means
The @CustomSerialization annotation on a REST resource (class or method) names a class implementing BiFunction that performs custom JSON serialization. Because Quarkus instantiates this class reflectively at runtime, it must have a public no-argument constructor. During the build, if the Jandex index can resolve the class and it lacks a no-args constructor, the deployment fails with this IllegalArgumentException.
Source
Thrown at extensions/resteasy-reactive/rest-jackson/deployment/src/main/java/io/quarkus/resteasy/reactive/jackson/deployment/processor/ResteasyReactiveJacksonProcessor.java:299
}
}
if (resourceClass.annotationsMap().containsKey(CUSTOM_SERIALIZATION)) {
jacksonFeatures.add(JacksonFeatureBuildItem.Feature.CUSTOM_SERIALIZATION);
for (AnnotationInstance instance : resourceClass.annotationsMap().get(CUSTOM_SERIALIZATION)) {
AnnotationValue annotationValue = instance.value();
if (annotationValue == null) {
continue;
}
Type biFunctionType = annotationValue.asClass();
if (biFunctionType == null) {
continue;
}
ClassInfo biFunctionClassInfo = index.getIndex().getClassByName(biFunctionType.name());
if (biFunctionClassInfo == null) {
// be lenient
} else {
if (!biFunctionClassInfo.hasNoArgsConstructor()) {
throw new IllegalArgumentException(
"Class '" + biFunctionClassInfo.name() + "' must contain a no-args constructor");
}
}
reflectiveClassProducer.produce(
ReflectiveClassBuildItem.builder(biFunctionType.name().toString())
.reason(getClass().getName())
.build());
recorder.recordCustomSerialization(getTargetId(instance), biFunctionType.name().toString());
}
}
if (resourceClass.annotationsMap().containsKey(CUSTOM_DESERIALIZATION)) {
jacksonFeatures.add(JacksonFeatureBuildItem.Feature.CUSTOM_DESERIALIZATION);
for (AnnotationInstance instance : resourceClass.annotationsMap().get(CUSTOM_DESERIALIZATION)) {
AnnotationValue annotationValue = instance.value();
if (annotationValue == null) {
continue;
}
Type biFunctionType = annotationValue.asClass();View on GitHub (pinned to e1c734241f)
Solutions
- Add a public no-argument constructor to the BiFunction class named in the message
- Move required dependencies into the apply(...) call or use static configuration instead of constructor injection
- Make the class a static nested class or top-level class with an explicit no-arg constructor
- Verify the class actually implements BiFunction<Object, ObjectMapper, Object> (or the deserialization equivalent) with a stateless design
Example fix
// before
class MySerializer implements BiFunction<Object, ObjectMapper, Object> {
private final ObjectMapper mapper;
MySerializer(ObjectMapper m) { this.mapper = m; }
}
// after
class MySerializer implements BiFunction<Object, ObjectMapper, Object> {
public MySerializer() { }
@Override
public Object apply(Object value, ObjectMapper mapper) { ... }
} Defensive patterns
Strategy: validation
Validate before calling
Class<?> c = MySerializer.class;
try {
c.getDeclaredConstructor().setAccessible(true);
c.getDeclaredConstructor().newInstance();
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException("@CustomSerialization class " + c.getName() + " needs a public no-args constructor");
} Type guard
static boolean hasNoArgsConstructor(Class<?> c) {
try { c.getDeclaredConstructor(); return true; }
catch (NoSuchMethodException e) { return false; }
} Try / catch
try {
deploy();
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().contains("must contain a no-args constructor")) {
// fix the serializer class named in the message
}
} Prevention
- Always give BiFunction serializers an explicit public no-args constructor
- Make nested serializer classes static
- Never inject constructor dependencies into @CustomSerialization targets
- Write a unit test that instantiates the class via new before deploying
When it happens
Trigger: Annotating a resource with @CustomSerialization(value = MyBiFunction.class) where MyBiFunction only has parameterized constructors (e.g. takes ObjectMapper or config in its constructor).
Common situations: Writing the custom serializer as an inner class capturing outer state; adding constructor injection to an existing BiFunction serializer; copying a Spring-style bean pattern where constructor args are expected.
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/42aaff388149c68b.
Report an issue: GitHub.