{"record":{"id":"35f0ca262c63399a","repo":"hibernate/hibernate-orm","slug":"unable-to-locate-constructor-for-embeddable-35f0ca","errorCode":null,"errorMessage":"Unable to locate constructor for embeddable","messagePattern":"Unable to locate constructor for embeddable","errorType":"exception","errorClass":"InstantiationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/metamodel/internal/EmbeddableInstantiatorRecordStandard.java","lineNumber":31,"sourceCode":"import static org.hibernate.internal.util.ReflectHelper.getConstructorOrNull;\nimport static org.hibernate.internal.util.ReflectHelper.getRecordComponentTypes;\n\n/**\n * Support for instantiating embeddables as record representation\n */\npublic class EmbeddableInstantiatorRecordStandard extends AbstractPojoInstantiator implements EmbeddableInstantiator {\n\n\tprotected final Constructor<?> constructor;\n\n\tpublic EmbeddableInstantiatorRecordStandard(Class<?> javaType) {\n\t\tsuper( javaType );\n\t\tconstructor = getConstructorOrNull( javaType, getRecordComponentTypes( javaType ) );\n\t}\n\n\t@Override\n\tpublic Object instantiate(ValueAccess valuesAccess) {\n\t\tif ( constructor == null ) {\n\t\t\tthrow new InstantiationException( \"Unable to locate constructor for embeddable\", getMappedPojoClass() );\n\t\t}\n\n\t\ttry {\n\t\t\treturn constructor.newInstance( valuesAccess.getValues() );\n\t\t}\n\t\tcatch ( Exception e ) {\n\t\t\tthrow new InstantiationException( \"Could not instantiate entity\", getMappedPojoClass(), e );\n\t\t}\n\t}\n}\n","sourceCodeStart":13,"sourceCodeEnd":42,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/metamodel/internal/EmbeddableInstantiatorRecordStandard.java#L13-L42","documentation":"Thrown by EmbeddableInstantiatorRecordStandard.instantiate when the constructor resolved in the class constructor phase is null. The constructor is looked up once via getConstructorOrNull(javaType, getRecordComponentTypes(javaType)); it remains null when the mapped embeddable class does not expose a constructor whose parameter types match the record component types - in practice, when record representation is used for a class that is not a genuine record, or whose canonical constructor cannot be reflectively matched.","triggerScenarios":"Boot succeeds but the first load/query of the embeddable calls instantiate() and hits the null-constructor branch; @Representation(RepresentationMode.RECORD) on a non-record embeddable class; a record type consumed through a custom CompositeUserType whose returnedClass is not the record itself; record loaded through a JavaType descriptor reporting non-matching component types.","commonSituations":"Hibernate 6 migrations where RepresentationMode.RECORD was introduced to keep old mappings; misconfigured CompositeUserType implementations; annotation processors generating embeddable stubs that are not records.","solutions":["Confirm the mapped class is a real record and the mapping uses it directly (not a wrapper class with @Representation(RECORD))","If the class must stay a POJO, remove the record representation setting and let Hibernate use POJO instantiation","For CompositeUserType, make returnedClass() return the record class whose canonical constructor matches the mapped property types","Catch InstantiationException during a warm-up read right after SessionFactory creation so mapping problems surface at startup, not in production queries"],"exampleFix":"// before - CompositeUserType returns a non-record holder but mapping declares RECORD\npublic class MoneyType implements CompositeUserType<MoneyHolder> {\n    public Class<MoneyHolder> returnedClass() { return MoneyHolder.class; } // plain class\n}\n\n// after - return the actual record\ntype public class MoneyType implements CompositeUserType<Money> {\n    public Class<Money> returnedClass() { return Money.class; }  // record\n}\npublic record Money(BigDecimal amount, Currency currency) {}","handlingStrategy":"validation","validationCode":"// Fail fast at app start instead of first query\nClass<?> embeddable = Money.class;\nif ( !embeddable.isRecord() ) {\n    throw new IllegalStateException(\"Embeddable \" + embeddable.getName() + \" must be a record under RECORD representation\");\n}\nClass<?>[] ctorTypes = Arrays.stream(embeddable.getRecordComponents()).map(RecordComponent::getType).toArray(Class[]::new);\nembeddable.getDeclaredConstructor(ctorTypes).setAccessible(true); // throws if unresolvable/inaccessible","typeGuard":"static boolean hasCanonicalRecordConstructor(Class<?> c) {\n    if (!c.isRecord()) return false;\n    try {\n        Class<?>[] t = Arrays.stream(c.getRecordComponents()).map(RecordComponent::getType).toArray(Class[]::new);\n        c.getDeclaredConstructor(t);\n        return true;\n    } catch (NoSuchMethodException | SecurityException e) { return false; }\n}","tryCatchPattern":"catch ( org.hibernate.InstantiationException e ) {\n    if ( \"Unable to locate constructor for embeddable\".equals(e.getMessage()) ) {\n        throw new MappingError(\"Embeddable \" + e.getMessage() + \" has no canonical record constructor - fix the mapping\", e);\n    }\n    throw e;\n}","preventionTips":["Keep the embeddable class a plain record and let Hibernate resolve the canonical constructor itself","Make CompositeUserType.returnedClass() return the actual record class","Smoke-test EntityManagerFactory creation plus one entity load per embeddable in CI"],"tags":["hibernate","jpa","embeddable","record","composite-user-type","representation-mode"],"backgroundTag":"embeddable-constructor-not-found","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}