{"record":{"id":"e6ad5cdbea7857fe","repo":"hibernate/hibernate-orm","slug":"struct-s-is-defined-by-multiple-components-s-b","errorCode":null,"errorMessage":"Struct [%s] is defined by multiple components %s but some columns are missing in [%s]: %s","messagePattern":"Struct \\[(.+?)\\] is defined by multiple components (.+?) but some columns are missing in \\[(.+?)\\]: (.+?)","errorType":"exception","errorClass":"MappingException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/boot/model/internal/AggregateComponentSecondPass.java","lineNumber":426,"sourceCode":"\t\t\tif ( column2 == null ) {\n\t\t\t\tmissingColumns.add( column1 );\n\t\t\t}\n\t\t\telse if ( !column1.getSqlType().equals( column2.getSqlType() ) ) {\n\t\t\t\tthrow new MappingException(\n\t\t\t\t\t\tString.format(\n\t\t\t\t\t\t\t\t\"Struct [%s] of class [%s] is defined by multiple components with different mappings [%s] and [%s] for column [%s]\",\n\t\t\t\t\t\t\t\tudt1.getName(),\n\t\t\t\t\t\t\t\tcomponentClassDetails.getName(),\n\t\t\t\t\t\t\t\tcolumn1.getSqlType(),\n\t\t\t\t\t\t\t\tcolumn2.getSqlType(),\n\t\t\t\t\t\t\t\tcolumn1.getCanonicalName()\n\t\t\t\t\t\t)\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tif ( !missingColumns.isEmpty() ) {\n\t\t\tthrow new MappingException(\n\t\t\t\t\tString.format(\n\t\t\t\t\t\t\t\"Struct [%s] is defined by multiple components %s but some columns are missing in [%s]: %s\",\n\t\t\t\t\t\t\tudt1.getName(),\n\t\t\t\t\t\t\tfindComponentClasses(),\n\t\t\t\t\t\t\tcomponentClassDetails.getName(),\n\t\t\t\t\t\t\tmissingColumns\n\t\t\t\t\t)\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate TreeSet<String> findComponentClasses() {\n\t\tfinal TreeSet<String> componentClasses = new TreeSet<>();\n\t\tcontext.getMetadataCollector().visitRegisteredComponents(\n\t\t\t\tc -> {\n\t\t\t\t\tif ( component.getStructName().equals( c.getStructName() ) ) {\n\t\t\t\t\t\tcomponentClasses.add( c.getComponentClassName() );\n\t\t\t\t\t}","sourceCodeStart":408,"sourceCodeEnd":444,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AggregateComponentSecondPass.java#L408-L444","documentation":"Final stage of validateEqual: every column of one definition of a struct must exist in the other definition. Columns present in udt1 with no counterpart in udt2 are collected and reported in this MappingException, which lists the struct name, the component classes, and the missing columns.","triggerScenarios":"Two components share a @Struct(name=...) where one maps extra fields/columns the other lacks - overlapping-but-not-identical field sets (the count check passed after one side dropped fields, but names still diverge).","commonSituations":"Removing a field from one of two duplicated struct embeddables; partial refactors of a shared UDT model; merging modules where two Address-like embeddables ended up with the same struct name.","solutions":["Add the missing columns to the incomplete component so both map the identical column set","Or remove the extra columns from the richer component","Best: replace both with one canonical embeddable class for that struct","If the mappings are intentionally different, change the struct name of one"],"exampleFix":"// before: struct A maps 2 columns, struct B (same name) misses 'zip'\n@Embeddable @Struct(name = \"address\")\npublic class FullAddress { String street; String zip; }\n\n@Embeddable @Struct(name = \"address\")\npublic class ShortAddress { String street; }   // 'zip' missing -> error\n\n// after: identical column sets\n@Embeddable @Struct(name = \"address\")\npublic class FullAddress { String street; String zip; }\n\n@Embeddable @Struct(name = \"address\")\npublic class ShortAddress { String street; @Column(name = \"zip\") String zipCode; } // aligned","handlingStrategy":"validation","validationCode":"// Before boot: assert identical effective column-name sets per struct name\nstatic boolean columnSetsMatch(Class<?> a, Class<?> b) {\n    Set<String> namesA = columnMap(a).keySet();\n    Set<String> namesB = columnMap(b).keySet();\n    return namesA.equals(namesB);\n}","typeGuard":null,"tryCatchPattern":"try {\n    sessionFactory = metadata.buildSessionFactory();\n} catch (MappingException e) {\n    if (e.getMessage().contains(\"some columns are missing\")) {\n        throw new IllegalStateException(\"Struct components map different column sets\", e);\n    }\n    throw e;\n}","preventionTips":["Keep a single canonical embeddable per struct name","When editing a struct embeddable, check for sibling classes with the same @Struct name","Add a CI check that maps sharing a struct name have equal field/column sets"],"tags":["hibernate","struct","missing-column","mapping","udt"],"backgroundTag":"struct-definition-conflict","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}