{"record":{"id":"f2aa43840910c9f2","repo":"hibernate/hibernate-orm","slug":"component-type-specifies-properties-for-th","errorCode":null,"errorMessage":"component type [{}] specifies {} properties for the instantiator but has {} properties","messagePattern":"component type \\[(.+?)\\] specifies (.+?) properties for the instantiator but has (.+?) properties","errorType":"exception","errorClass":"MappingException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/mapping/Component.java","lineNumber":820,"sourceCode":"\t\t\tif ( generator instanceof Configurable configurable ) {\n\t\t\t\tconfigurable.initialize( context );\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void prepareForMappingModel() {\n\t\t// This call will initialize the type properly\n\t\tgetType();\n\t}\n\n\t@Override\n\tpublic boolean isValid(MappingContext mappingContext) throws MappingException {\n\t\tif ( !super.isValid( mappingContext ) ) {\n\t\t\treturn false;\n\t\t}\n\t\tif ( instantiatorPropertyNames != null ) {\n\t\t\tif ( instantiatorPropertyNames.length < properties.size() ) {\n\t\t\t\tthrow new MappingException( \"component type [\" + componentClassName + \"] specifies \" + instantiatorPropertyNames.length + \" properties for the instantiator but has \" + properties.size() + \" properties\" );\n\t\t\t}\n\t\t\tfinal HashSet<String> assignedPropertyNames = CollectionHelper.setOfSize( properties.size() );\n\t\t\tfor ( String instantiatorPropertyName : instantiatorPropertyNames ) {\n\t\t\t\tif ( getProperty( instantiatorPropertyName ) == null ) {\n\t\t\t\t\tthrow new MappingException( \"could not find property [\" + instantiatorPropertyName + \"] defined in the @Instantiator withing component [\" + componentClassName + \"]\" );\n\t\t\t\t}\n\t\t\t\tassignedPropertyNames.add( instantiatorPropertyName );\n\t\t\t}\n\t\t\tif ( assignedPropertyNames.size() != properties.size() ) {\n\t\t\t\tfinal ArrayList<String> missingProperties = new ArrayList<>();\n\t\t\t\tfor ( var property : properties ) {\n\t\t\t\t\tfinal String propertyName = property.getName();\n\t\t\t\t\tif ( !assignedPropertyNames.contains( propertyName ) ) {\n\t\t\t\t\t\tmissingProperties.add( propertyName );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthrow new MappingException( \"component type [\" + componentClassName + \"] has \" + properties.size() + \" properties but the instantiator only assigns \" + assignedPropertyNames.size() + \" properties. missing properties: \" + missingProperties );\n\t\t\t}","sourceCodeStart":802,"sourceCodeEnd":838,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/mapping/Component.java#L802-L838","documentation":"Component#isValid rejects an embeddable whose @Instantiator-annotated constructor declares fewer parameters than the embeddable has persistent properties. Hibernate (6.6+) requires the chosen instantiator to cover every property so hydration can never leave a field unset.","triggerScenarios":"A hand-written partial constructor is marked @Instantiator while the class has more fields; a new field was added to the embeddable without updating the annotated constructor; a canonical constructor was replaced by a convenience constructor.","commonSituations":"Evolving @Embeddable/@EmbeddedId classes that use explicit @Instantiator; porting classes with overloaded constructors to Hibernate 6.6; replacing records with plain classes that have partial constructors.","solutions":["Extend the annotated constructor so it accepts every persistent property of the embeddable.","Or remove @Instantiator so Hibernate selects the canonical all-args constructor itself.","For shapes that cannot be 1:1, register a dedicated @EmbeddableInstantiator implementation instead of annotating a constructor."],"exampleFix":"// before\n@Embeddable\npublic class Name {\n    private String first;\n    private String last;\n\n    @Instantiator\n    Name(String first) { this.first = first; }\n}\n\n// after\n@Embeddable\npublic class Name {\n    private String first;\n    private String last;\n\n    @Instantiator\n    Name(String first, String last) {\n        this.first = first;\n        this.last = last;\n    }\n}","handlingStrategy":"validation","validationCode":"static boolean coversAllProperties(Class<?> embeddable, Constructor<?> ctor) {\n    long fields = Arrays.stream(embeddable.getDeclaredFields())\n            .filter(f -> !Modifier.isStatic(f.getModifiers()))\n            .count();\n    return ctor.getParameterCount() >= fields;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer records or canonical all-args constructors for embeddables - coverage is automatic.","When adding a field to an embeddable with an @Instantiator constructor, update the constructor in the same commit.","Run Metadata building in unit tests so isValid failures hit CI, not production."],"tags":["hibernate","orm","mapping","embeddable","instantiator","constructor"],"backgroundTag":"embeddable-instantiator-mismatch","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}