quarkusio/quarkus · error · IllegalArgumentException

Couldn't extract all parameters information for constructor

Error message

Couldn't extract all parameters information for constructor ${selectedCtor} for type ${expectedType}

What it means

For classes recorded via constructor-parameter extraction, Quarkus reflects on constructor parameter names to map them to fields/properties. If it cannot extract names for every parameter (constructorParamNameMap.size() != parameterCount), reconstruction cannot be guaranteed and recording is rejected. This usually means the class was compiled without -parameters (no LocalVariableTable/parameter name info) and no other name source (annotations, recorded metadata) exists.

Source

Thrown at core/deployment/src/main/java/io/quarkus/deployment/recording/BytecodeRecorderImpl.java:1274

            Constructor<?> selectedCtor = null;
            if (ctors.length == 1) {
                // if there is a single constructor we use it regardless of the presence of @RecordableConstructor annotation
                selectedCtor = ctors[0];
            }
            for (Constructor<?> ctor : ctors) {
                if (RecordingAnnotationsUtil.isRecordableConstructor(ctor)) {
                    selectedCtor = ctor;
                    break;
                }
            }
            if (selectedCtor != null) {
                nonDefaultConstructorHolder = new NonDefaultConstructorHolder(selectedCtor, null);
                final var parameterCount = selectedCtor.getParameterCount();
                nonDefaultConstructorHandles = new DeferredParameter[parameterCount];
                extractConstructorParameterNames(selectedCtor, constructorParamNameMap);

                if (constructorParamNameMap.size() != parameterCount) {
                    throw new IllegalArgumentException("Couldn't extract all parameters information for constructor "
                            + selectedCtor + " for type " + expectedType);
                }
            }
        }

        Set<String> handledProperties = new HashSet<>();
        Property[] desc = PropertyUtils.getPropertyDescriptors(param);
        FieldsHelper fieldsHelper = new FieldsHelper(param.getClass());
        for (Property i : desc) {
            if (!i.getDeclaringClass().getPackageName().startsWith("java.")) {
                // check if the getter is ignored
                if ((i.getReadMethod() != null) && RecordingAnnotationsUtil.isIgnored(i.getReadMethod())) {
                    continue;
                }
                // check if the matching field is ignored
                Field field = fieldsHelper.getDeclaredField(i.getName());
                if (field != null && ignoreField(field)) {
                    continue;

View on GitHub (pinned to e1c734241f)

Solutions

  1. Compile the class's module with -parameters (maven-compiler-plugin <parameters>true</parameters>)
  2. Explicitly register the constructor and its parameter names with the recording machinery instead of relying on reflection
  3. Rewrite the object into a type with a default constructor plus getters/setters so name extraction is not needed

Example fix

// before
<artifact>maven-compiler-plugin</artifact> <!-- no config -->
// after
<configuration><parameters>true</parameters></configuration>
Defensive patterns

Strategy: validation

Validate before calling

Parameter[] ps = ctor.getParameters();
boolean allNamed = Arrays.stream(ps).allMatch(p ->
    !p.isNamePresent() || !p.getName().matches("arg\d+"));
if (!allNamed) throw new IllegalStateException("Compile " + ctor.getDeclaringClass()
    + " with -parameters before recording");

Type guard

boolean hasParameterNames(Constructor<?> c) {
    return Arrays.stream(c.getParameters())
        .allMatch(p -> p.isNamePresent() && !p.getName().matches("arg\d+"));
}

Try / catch

try {
    recorder.record(value);
} catch (IllegalArgumentException e) {
    if (String.valueOf(e.getMessage()).startsWith("Couldn't extract all parameters information")) {
        throw new IllegalStateException("Rebuild " + value.getClass() + " with -parameters", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Recording an object whose selected constructor's parameter names cannot all be resolved — e.g. the class was compiled without the -parameters javac flag and parameter names are arg0, arg1...; a constructor using parameters not backed by matching fields.

Common situations: Third-party jars or prebuilt dependencies (compiled without -parameters) passed into @Record methods; native-image builds where parameter names are stripped; extension relying on reflected parameter names of a dependency class.

Related errors


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