{"record":{"id":"92366b0f7ecaa6f1","repo":"hibernate/hibernate-orm","slug":"generated-attribute-cannot-be-insert-or-updat","errorCode":null,"errorMessage":"'generated' attribute cannot be 'insert' or 'update' for version/timestamp property","messagePattern":"'generated' attribute cannot be 'insert' or 'update' for version/timestamp property","errorType":"exception","errorClass":"MappingException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java","lineNumber":2248,"sourceCode":"\t\t\t\t\tcolumns( property.getValue() ) );\n\t\t}\n\t}\n\n\tprivate String toCascadeString(EnumSet<CascadeType> defaultCascadeTypes) {\n\t\treturn isEmpty( defaultCascadeTypes ) ? \"none\" : renderCascadeTypeList( defaultCascadeTypes );\n\t}\n\n\tprivate static void handleGenerationTiming(\n\t\t\tMappingDocument mappingDocument,\n\t\t\tAttributeSource propertySource,\n\t\t\tProperty property,\n\t\t\tGenerationTiming timing) {\n\t\tif ( timing != null ) {\n\t\t\tif ( (timing == GenerationTiming.INSERT || timing == GenerationTiming.UPDATE)\n\t\t\t\t\t&& property.getValue() instanceof SimpleValue simpleValue\n\t\t\t\t\t&& simpleValue.isVersion() ) {\n\t\t\t\t// this is enforced by DTD, but just make sure\n\t\t\t\tthrow new MappingException(\n\t\t\t\t\t\t\"'generated' attribute cannot be 'insert' or 'update' for version/timestamp property\",\n\t\t\t\t\t\tmappingDocument.getOrigin()\n\t\t\t\t);\n\t\t\t}\n\t\t\tif ( timing != GenerationTiming.NEVER ) {\n\t\t\t\tproperty.setValueGeneratorCreator( context\n\t\t\t\t\t\t-> new GeneratedGeneration( timing.getEventTypes() ) );\n\n\t\t\t\t// generated properties can *never* be insertable...\n\t\t\t\tif ( property.isInsertable() && timing.includesInsert() ) {\n\t\t\t\t\tBOOT_LOGGER.tracef(\n\t\t\t\t\t\t\t\"Property [%s] specified %s generation, setting insertable to false: %s\",\n\t\t\t\t\t\t\tpropertySource.getName(),\n\t\t\t\t\t\t\ttiming.name(),\n\t\t\t\t\t\t\tmappingDocument.getOrigin()\n\t\t\t\t\t);\n\t\t\t\t\tproperty.setInsertable( false );\n\t\t\t\t}","sourceCodeStart":2230,"sourceCodeEnd":2266,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java#L2230-L2266","documentation":"For <version>/<timestamp> properties Hibernate only allows generated='never' (default) or generated='always' (fully DB-generated on both insert and update). INSERT- or UPDATE-timed generation is rejected because the version value must be written on every bump for optimistic locking to stay correct; the DTD disallows it and this binder check enforces it for non-XSD-validated mappings.","triggerScenarios":"<version name='ver' generated='insert'/> or <timestamp name='ts' generated='update'/> in hbm.xml where the value is a SimpleValue flagged as the version.","commonSituations":"Copying generated attributes from <id> or regular property mappings onto a version column; DB-defaulted version columns misunderstood as partially generated.","solutions":["Remove the generated attribute (default never) from the version/timestamp element","If the DB generates the version on every write, use generated='always' instead","If the column is only insert-generated but is not truly the optimistic-lock version, map it as a plain <property generated='insert'> instead of <version>"],"exampleFix":"// before\n<version name='ver' column='ver' generated='insert'/>\n\n// after\n<version name='ver' column='ver' generated='always'/>","handlingStrategy":"validation","validationCode":"NodeList versions = doc.getElementsByTagName(\"version\");\nNodeList stamps = doc.getElementsByTagName(\"timestamp\");\nBiPredicate<Element, String> bad = (e, attr) -> \"insert\".equals(e.getAttribute(attr)) || \"update\".equals(e.getAttribute(attr));\nfor (int i = 0; i < versions.getLength(); i++) { if (bad.test((Element) versions.item(i), \"generated\")) throw new IllegalStateException(\"version generated must be never|always\"); }\nfor (int i = 0; i < stamps.getLength(); i++) { if (bad.test((Element) stamps.item(i), \"generated\")) throw new IllegalStateException(\"timestamp generated must be never|always\"); }","typeGuard":null,"tryCatchPattern":"catch (MappingException e) at bootstrap; remove or change generated= on the flagged <version>/<timestamp> to 'always' or omit it, then rebuild.","preventionTips":["Only use generated='always' or omit generated on version/timestamp mappings","Do not copy generated attributes from id/property mappings onto versions","XSD-validate mappings: the DTD/XSD already disallows this combination"],"tags":["hibernate","hbm-mapping","version","optimistic-locking","generated-columns"],"backgroundTag":"generated-column-misconfiguration","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}