{"record":{"id":"be2fb14a3ecae608","repo":"hibernate/hibernate-orm","slug":"property-path-specifies-columncount-attr","errorCode":null,"errorMessage":"Property '${path}' specifies ${columnCount} '@AttributeOverride's but the overridden property has ${overriddenColumnCount} columns (every column must have exactly one '@AttributeOverride')","messagePattern":"Property '(.+?)' specifies (.+?) '@AttributeOverride's but the overridden property has (.+?) columns \\(every column must have exactly one '@AttributeOverride'\\)","errorType":"exception","errorClass":"AnnotationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedColumn.java","lineNumber":768,"sourceCode":"\t\t\t\t\t\tactualColumns,\n\t\t\t\t\t\tfractionalSeconds\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static jakarta.persistence.Column[] overrideColumns(\n\t\t\tjakarta.persistence.Column[] columns,\n\t\t\tPropertyHolder propertyHolder,\n\t\t\tPropertyData inferredData ) {\n\t\tfinal String path = getPath( propertyHolder, inferredData );\n\t\tfinal var overriddenCols = propertyHolder.getOverriddenColumn( path );\n\t\tif ( overriddenCols != null ) {\n\t\t\t//check for overridden first\n\t\t\tif ( columns != null && overriddenCols.length != columns.length ) {\n\t\t\t\t//TODO: unfortunately, we never actually see this nice error message, since\n\t\t\t\t//      PersistentClass.validate() gets called first and produces a worse message\n\t\t\t\tthrow new AnnotationException( \"Property '\" + path\n\t\t\t\t\t\t+ \"' specifies \" + columns.length\n\t\t\t\t\t\t+ \" '@AttributeOverride's but the overridden property has \" + overriddenCols.length\n\t\t\t\t\t\t+ \" columns (every column must have exactly one '@AttributeOverride')\" );\n\t\t\t}\n\t\t\tif ( BOOT_LOGGER.isTraceEnabled() ) {\n\t\t\t\tBOOT_LOGGER.columnMappingOverridden( inferredData.getPropertyName() );\n\t\t\t}\n\t\t\treturn isEmpty( overriddenCols ) ? null : overriddenCols;\n\t\t}\n\t\telse {\n\t\t\treturn columns;\n\t\t}\n\t}\n\n\tprivate static AnnotatedColumns buildExplicitColumns(\n//\t\t\tComment comment,\n\t\t\tPropertyHolder propertyHolder,\n\t\t\tPropertyData inferredData,","sourceCodeStart":750,"sourceCodeEnd":786,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedColumn.java#L750-L786","documentation":"When @AttributeOverride is applied to a property, AnnotatedColumn.overrideColumns compares the number of supplied jakarta.persistence.Column entries with the number of columns the overridden property actually maps. A multi-column mapping (composite basic types, embeddables mapping several columns) needs exactly one @Column override per mapped column; any other count throws this AnnotationException. (A code comment notes PersistentClass.validate() often fires first with a vaguer message.)","triggerScenarios":"Overriding a property that maps N>1 columns with fewer/more @AttributeOverride entries - e.g. overriding only one column of a two-column user type or of a nested embeddable, or listing overrides for a single-column property twice.","commonSituations":"Applying @AttributeOverride to embeddables containing multi-column fields (monetary amounts, durations, custom composite types); copying override blocks between embeddables with different column counts; adding a field to an embeddable without adding its override.","solutions":["Count the columns the overridden property maps and supply exactly that many @Column entries in @AttributeOverrides","If you only meant to rename one column of a composite, still override every column of that composite","For overriding associations, use @AssociationOverride instead of @AttributeOverride","If counts look right, check that a different validation error is not masking this one - fix the first mapping error reported"],"exampleFix":"// before: two-column property overridden once\n@Embeddable\npublic class Money {                       // maps amount + currency -> 2 columns\n    BigDecimal amount;\n    @Column(length = 3) String currency;\n}\n\n@Entity\npublic class Payment {\n    @Embedded\n    @AttributeOverrides({@AttributeOverride(name = \"amount\", column = @Column(name = \"pay_amount\"))})\n    private Money money;                   // 1 override for 2 columns -> error\n}\n\n// after: every column overridden exactly once\n@Embedded\n@AttributeOverrides({\n    @AttributeOverride(name = \"amount\", column = @Column(name = \"pay_amount\")),\n    @AttributeOverride(name = \"currency\", column = @Column(name = \"pay_currency\"))\n})\nprivate Money money;","handlingStrategy":"validation","validationCode":"// Before boot: known multi-column embeddables need an override per column\n// Money maps 2 columns -> require both 'amount' and 'currency' overrides\nstatic boolean overridesComplete(Class<?> entity, Map<String, Integer> columnsByPath) {\n    for (Field f : entity.getDeclaredFields()) {\n        AttributeOverrides o = f.getAnnotation(AttributeOverrides.class);\n        if (o == null) continue;\n        long distinct = Arrays.stream(o.value())\n                .map(AttributeOverride::name).distinct().count();\n        Integer expected = columnsByPath.get(f.getName());\n        if (expected != null && distinct != expected) return false;\n    }\n    return true;\n}","typeGuard":null,"tryCatchPattern":"try {\n    final SessionFactory sf = new MetadataSources(standardServiceRegistry)\n            .addAnnotatedClass(MyEntity.class)\n            .buildMetadata()\n            .buildSessionFactory();\n} catch (AnnotationException | MappingException e) {\n    throw new IllegalStateException(\"Invalid ORM mapping, aborting startup: \" + e.getMessage(), e);\n}","preventionTips":["Document the column count of every composite type you use","When adding a field to an embeddable, update every @AttributeOverrides block that targets it","Prefer a full, explicit override list over partial renames"],"tags":["hibernate","jpa","attribute-override","embeddable","multi-column","mapping"],"backgroundTag":"attribute-override-count-mismatch","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}