{"record":{"id":"81d5d4f9c0462f7c","repo":"hibernate/hibernate-orm","slug":"map-index-element-must-specify-a-type-s","errorCode":null,"errorMessage":"map index element must specify a type: %s","messagePattern":"map index element must specify a type: (.+?)","errorType":"exception","errorClass":"MappingException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java","lineNumber":3699,"sourceCode":"\t\t\t\tcomponentBinding,\n\t\t\t\tnull,\n\t\t\t\tpluralAttributeSource.getName(),\n\t\t\t\tfalse\n\t\t);\n\t\tcollectionBinding.setIndex( componentBinding );\n\t}\n\n\tprivate void bindBasicMapKey(\n\t\t\tMappingDocument mappingDocument,\n\t\t\tIndexedPluralAttributeSource pluralAttributeSource,\n\t\t\torg.hibernate.mapping.Map collectionBinding,\n\t\t\tPluralAttributeMapKeySourceBasic mapKeySource) {\n\t\tfinal var value =\n\t\t\t\tnew BasicValue( mappingDocument,\n\t\t\t\t\t\tcollectionBinding.getCollectionTable() );\n\t\tbindSimpleValueType( mappingDocument, mapKeySource.getTypeInformation(), value );\n\t\tif ( !value.isTypeSpecified() ) {\n\t\t\tthrow new MappingException(\n\t\t\t\t\t\"map index element must specify a type: \"\n\t\t\t\t\t+ pluralAttributeSource.getAttributeRole().getFullPath(),\n\t\t\t\t\tmappingDocument.getOrigin()\n\t\t\t);\n\t\t}\n\n\t\trelationalObjectBinder.bindColumnsAndFormulas(\n\t\t\t\tmappingDocument,\n\t\t\t\tmapKeySource.getRelationalValueSources(),\n\t\t\t\tvalue,\n\t\t\t\ttrue,\n\t\t\t\tcontext -> database.toIdentifier( IndexedCollection.DEFAULT_INDEX_COLUMN_NAME )\n\t\t);\n\n\t\tcollectionBinding.setIndex( value );\n\t}\n\n\tprivate class ManyToOneColumnBinder implements ImplicitColumnNamingSecondPass {","sourceCodeStart":3681,"sourceCodeEnd":3717,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java#L3681-L3717","documentation":"For a <map> with a basic (non-entity, non-composite) index, Hibernate builds a BasicValue for the map key from <map-key>. There is no backing Java property to reflect on, so if after binding the type information value.isTypeSpecified() is false - no type= on <map-key> and nothing inferable - the key column's type is unknown and binding fails.","triggerScenarios":"<map><key .../><map-key column='lang'/><element .../></map> - a <map-key> element without a type attribute; also a map-key whose type attribute name is unresolvable so isTypeSpecified() ends up false.","commonSituations":"Converting a <set> to a <map> and forgetting the key type; assuming Hibernate guesses the index type like it can for POJO <id> properties (it cannot - a map key has no property to reflect on).","solutions":["Add the needed type to the <map-key> element, e.g. <map-key column='lang' type='string'/>","For composite keys use <composite-map-key class='...'> and for entity keys use <map-key-many-to-many class='...'> instead of a typed basic <map-key>"],"exampleFix":"// before\n<map name='labels' table='labels'>\n    <key column='item_id'/>\n    <map-key column='lang'/>\n    <element column='text' type='string'/>\n</map>\n\n// after\n<map name='labels' table='labels'>\n    <key column='item_id'/>\n    <map-key column='lang' type='string'/>\n    <element column='text' type='string'/>\n</map>","handlingStrategy":"validation","validationCode":"NodeList maps = doc.getElementsByTagName(\"map\");\nfor (int i = 0; i < maps.getLength(); i++) {\n    Element map = (Element) maps.item(i);\n    NodeList keys = map.getElementsByTagName(\"map-key\");\n    for (int j = 0; j < keys.getLength(); j++) {\n        Element k = (Element) keys.item(j);\n        if (k.getAttributeNode(\"type\") == null || k.getAttribute(\"type\").isBlank()) {\n            throw new IllegalStateException(\"<map-key> of \" + map.getAttribute(\"name\") + \" must declare a type\");\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":"catch (MappingException e) at bootstrap; the message names the map's attribute role. Add the matching type attribute to that <map-key> and rebuild.","preventionTips":["Always set type= on basic <map-key> elements","Use <composite-map-key> or <map-key-many-to-many> for non-basic keys","When converting <set> to <map>, remember the index needs an explicit type"],"tags":["hibernate","hbm-mapping","map","map-key","missing-type"],"backgroundTag":"orm-mapping-missing-type","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}