{"record":{"id":"42aaff388149c68b","repo":"quarkusio/quarkus","slug":"class-bifunctionclassinfo-name-must-contain-a","errorCode":null,"errorMessage":"Class '{biFunctionClassInfo.name}' must contain a no-args constructor","messagePattern":"Class '(.+?)' must contain a no-args constructor","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"extensions/resteasy-reactive/rest-jackson/deployment/src/main/java/io/quarkus/resteasy/reactive/jackson/deployment/processor/ResteasyReactiveJacksonProcessor.java","lineNumber":299,"sourceCode":"                }\n            }\n            if (resourceClass.annotationsMap().containsKey(CUSTOM_SERIALIZATION)) {\n                jacksonFeatures.add(JacksonFeatureBuildItem.Feature.CUSTOM_SERIALIZATION);\n                for (AnnotationInstance instance : resourceClass.annotationsMap().get(CUSTOM_SERIALIZATION)) {\n                    AnnotationValue annotationValue = instance.value();\n                    if (annotationValue == null) {\n                        continue;\n                    }\n                    Type biFunctionType = annotationValue.asClass();\n                    if (biFunctionType == null) {\n                        continue;\n                    }\n                    ClassInfo biFunctionClassInfo = index.getIndex().getClassByName(biFunctionType.name());\n                    if (biFunctionClassInfo == null) {\n                        // be lenient\n                    } else {\n                        if (!biFunctionClassInfo.hasNoArgsConstructor()) {\n                            throw new IllegalArgumentException(\n                                    \"Class '\" + biFunctionClassInfo.name() + \"' must contain a no-args constructor\");\n                        }\n                    }\n                    reflectiveClassProducer.produce(\n                            ReflectiveClassBuildItem.builder(biFunctionType.name().toString())\n                                    .reason(getClass().getName())\n                                    .build());\n                    recorder.recordCustomSerialization(getTargetId(instance), biFunctionType.name().toString());\n                }\n            }\n            if (resourceClass.annotationsMap().containsKey(CUSTOM_DESERIALIZATION)) {\n                jacksonFeatures.add(JacksonFeatureBuildItem.Feature.CUSTOM_DESERIALIZATION);\n                for (AnnotationInstance instance : resourceClass.annotationsMap().get(CUSTOM_DESERIALIZATION)) {\n                    AnnotationValue annotationValue = instance.value();\n                    if (annotationValue == null) {\n                        continue;\n                    }\n                    Type biFunctionType = annotationValue.asClass();","sourceCodeStart":281,"sourceCodeEnd":317,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/resteasy-reactive/rest-jackson/deployment/src/main/java/io/quarkus/resteasy/reactive/jackson/deployment/processor/ResteasyReactiveJacksonProcessor.java#L281-L317","documentation":"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.","triggerScenarios":"Annotating a resource with @CustomSerialization(value = MyBiFunction.class) where MyBiFunction only has parameterized constructors (e.g. takes ObjectMapper or config in its constructor).","commonSituations":"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.","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"],"exampleFix":"// before\nclass MySerializer implements BiFunction<Object, ObjectMapper, Object> {\n    private final ObjectMapper mapper;\n    MySerializer(ObjectMapper m) { this.mapper = m; }\n}\n\n// after\nclass MySerializer implements BiFunction<Object, ObjectMapper, Object> {\n    public MySerializer() { }\n    @Override\n    public Object apply(Object value, ObjectMapper mapper) { ... }\n}","handlingStrategy":"validation","validationCode":"Class<?> c = MySerializer.class;\ntry {\n    c.getDeclaredConstructor().setAccessible(true);\n    c.getDeclaredConstructor().newInstance();\n} catch (NoSuchMethodException e) {\n    throw new IllegalArgumentException(\"@CustomSerialization class \" + c.getName() + \" needs a public no-args constructor\");\n}","typeGuard":"static boolean hasNoArgsConstructor(Class<?> c) {\n    try { c.getDeclaredConstructor(); return true; }\n    catch (NoSuchMethodException e) { return false; }\n}","tryCatchPattern":"try {\n    deploy();\n} catch (IllegalArgumentException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"must contain a no-args constructor\")) {\n        // fix the serializer class named in the message\n    }\n}","preventionTips":["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"],"tags":["jackson","quarkus","custom-serialization","reflection"],"backgroundTag":"missing-no-arg-constructor","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}