{"record":{"id":"abec0154a06b64dd","repo":"hibernate/hibernate-orm","slug":"can-t-determine-field-assignment-for-constructor","errorCode":null,"errorMessage":"Can't determine field assignment for constructor: {}","messagePattern":"Can't determine field assignment for constructor: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/metamodel/internal/EmbeddableInstantiatorPojoIndirecting.java","lineNumber":33,"sourceCode":" */\npublic class EmbeddableInstantiatorPojoIndirecting\n\t\textends AbstractPojoInstantiator\n\t\timplements EmbeddableInstantiator {\n\tprotected final Constructor<?> constructor;\n\tprotected final int[] index;\n\n\tprotected EmbeddableInstantiatorPojoIndirecting(Constructor<?> constructor, int[] index) {\n\t\tsuper( constructor.getDeclaringClass() );\n\t\tthis.constructor = constructor;\n\t\tthis.index = index;\n\t}\n\n\tpublic static EmbeddableInstantiatorPojoIndirecting of(\n\t\t\tString[] propertyNames,\n\t\t\tConstructor<?> constructor,\n\t\t\tString[] componentNames) {\n\t\tif ( componentNames == null ) {\n\t\t\tthrow new IllegalArgumentException( \"Can't determine field assignment for constructor: \" + constructor );\n\t\t}\n\t\tfinal var index = new int[componentNames.length];\n\t\treturn EmbeddableHelper.resolveIndex( propertyNames, componentNames, index )\n\t\t\t\t? new EmbeddableInstantiatorPojoIndirectingWithGap( constructor, index )\n\t\t\t\t: new EmbeddableInstantiatorPojoIndirecting( constructor, index );\n\t}\n\n\t@Override\n\tpublic Object instantiate(ValueAccess valuesAccess) {\n\t\ttry {\n\t\t\tfinal var originalValues = valuesAccess.getValues();\n\t\t\tfinal var values = new Object[originalValues.length];\n\t\t\tfor ( int i = 0; i < values.length; i++ ) {\n\t\t\t\tvalues[i] = originalValues[index[i]];\n\t\t\t}\n\t\t\treturn constructor.newInstance( values );\n\t\t}\n\t\tcatch ( Exception e ) {","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/metamodel/internal/EmbeddableInstantiatorPojoIndirecting.java#L15-L51","documentation":"EmbeddableInstantiatorPojoIndirecting.of builds the instantiator used when an embeddable is created via constructor injection (the mapping's resolved instantiator) by matching constructor parameter names to embeddable property names. componentNames is derived from constructor parameter names via reflection; when it is null, name-based assignment is impossible, so Hibernate throws IllegalArgumentException(\"Can't determine field assignment for constructor: <ctor>\") during metamodel building.","triggerScenarios":"An embeddable with constructor injection whose constructor parameter names are unavailable in bytecode — i.e. the classes were compiled without the -parameters javac flag (so reflection returns arg0, arg1... and Hibernate's utility yields null) — triggering EmbeddableInstantiatorPojoIndirecting.of with a null componentNames array.","commonSituations":"Build systems or CI that don't pass -parameters (Lombok-heavy projects, Gradle defaults in some setups, annotation processors like gradle-incubating, third-party jars containing entities compiled without -parameters); after upgrading to a Hibernate version that started relying on parameter names for embeddable instantiation; IDE-compiled classes used in local runs.","solutions":["Compile with parameter names: Maven — <maven.compiler.parameters>true</maven.compiler.parameters> (or compilerArgument -parameters); Gradle — compileJava { options.compilerArgs << '-parameters' }.","Alternatively provide an explicit custom instantiator with @EmbeddableInstantiator(MyInstantiator.class) or an EmbeddableInstantiatorRegistration so Hibernate does not rely on reflection of parameter names.","Ensure @Embeddable classes are compiled by the same build config (watch out for prebuilt jars / annotation processors like Lombok configuring javac).","Add a canary test that builds the SessionFactory so this surfaces during the build, not at first runtime use."],"exampleFix":"// before (Gradle, no -parameters) — embeddable ctor injection fails\ncompileJava { }\n\n// after\ncompileJava {\n    options.compilerArgs << '-parameters'\n}","handlingStrategy":"validation","validationCode":"// build-time guard: fail if embeddable constructors lose parameter names\nConstructor<?> c = Address.class.getDeclaredConstructors()[0];\nboolean hasNames = !Arrays.stream(c.getParameters()).allMatch(p -> p.isNamePresent() == false);\nif (!hasNames) throw new IllegalStateException(\"Recompile with -parameters for embeddable constructor injection\");","typeGuard":"static boolean parameterNamesAvailable(Class<?> embeddable) {\n    return Arrays.stream(embeddable.getDeclaredConstructors())\n            .flatMap(c -> Arrays.stream(c.getParameters()))\n            .allMatch(Parameter::isNamePresent);\n}","tryCatchPattern":null,"preventionTips":["Always compile with -parameters (Maven compiler plugin or Gradle options.compilerArgs).","Watch dependencies/annotation processors (e.g. Lombok) that re-run javac without the flag.","Or sidestep reflection entirely with an explicit @EmbeddableInstantiator."],"tags":["hibernate","embeddable","constructor-injection","javac-parameters","build-config"],"backgroundTag":"missing-parameter-names","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}