{"record":{"id":"51566aa287101844","repo":"hibernate/hibernate-orm","slug":"identifier-of-entity","errorCode":null,"errorMessage":"Identifier of entity '","messagePattern":"Identifier of entity '","errorType":"exception","errorClass":"IdentifierGenerationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/event/internal/AbstractSaveEventListener.java","lineNumber":217,"sourceCode":"\t\t\tboolean useIdentityColumn,\n\t\t\t@Nonnull C context,\n\t\t\t@Nonnull EventSource source,\n\t\t\tboolean delayIdentityInserts) {\n\n\t\t// call this after generation of an id,\n\t\t// but before we retrieve an assigned id\n\t\tsource.runEntityLifecycleCallback( () -> persister.getEntityCallbacks().preCreate( entity ) );\n\n\t\tprocessIfSelfDirtinessTracker( entity, SelfDirtinessTracker::$$_hibernate_clearDirtyAttributes );\n\t\tprocessIfManagedEntity( entity, managedEntity -> managedEntity.$$_hibernate_setUseTracker( true ) );\n\n\t\tfinal var generator = persister.getGenerator();\n\t\tif ( !generator.generatesOnInsert()\n\t\t\t\t|| generator instanceof CompositeNestedGeneratedValueGenerator compositeGenerator\n\t\t\t\t\t\t&& compositeGenerator.hasAssignedValues() ) {\n\t\t\tid = persister.getIdentifier( entity, source );\n\t\t\tif ( id == null ) {\n\t\t\t\tthrow new IdentifierGenerationException( \"Identifier of entity '\" + persister.getEntityName()\n\t\t\t\t\t\t+ \"' must be manually assigned before calling 'persist()'\" );\n\t\t\t}\n\t\t}\n\n\t\tif ( EVENT_LISTENER_LOGGER.isTraceEnabled() ) {\n\t\t\tEVENT_LISTENER_LOGGER.persisting(\n\t\t\t\t\tinfoString( persister, id, source.getFactory() ) );\n\t\t}\n\n\t\tfinal EntityKey key;\n\t\tif ( useIdentityColumn ) {\n\t\t\tkey = null;\n\t\t}\n\t\telse {\n\t\t\tassert id != null;\n\t\t\tkey = entityKey( id, persister, source );\n\t\t}\n\t\treturn performSaveOrReplicate( entity, key, persister, useIdentityColumn, context, source, delayIdentityInserts );","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractSaveEventListener.java#L199-L235","documentation":"The entity's id is mapped as manually assigned (no generator that generates on insert — a plain @Id without @GeneratedValue, or an assigned generator). When persist() runs, AbstractSaveEventListener reads the identifier from the entity, finds null, and throws IdentifierGenerationException: the identifier must be set by application code before calling persist().","triggerScenarios":"em.persist()/session.persist() on an entity whose @Id field (no @GeneratedValue) is null; @IdClass/@EmbeddedId mappings where at least one attribute is unset; an entity assembled by a mapper or builder that skipped the id.","commonSituations":"DTO-to-entity mappings forgetting to copy the business key used as id; new entity types introduced without id generation; refactoring @GeneratedValue away without updating call sites.","solutions":["Set the identifier before persist: entity.setId(...)","If the id should be database-generated, add @GeneratedValue with the appropriate strategy","For composite ids, verify every attribute is populated (including parts set by @PrePersist-adjacent code)","Add a factory method for the entity that requires the id so callers cannot forget it"],"exampleFix":"// before\nem.persist(new Customer(\"Acme\")); // Customer.id is @Id without @GeneratedValue\n\n// after\nCustomer c = new Customer(\"Acme\");\nc.setId(nextCustomerId());\nem.persist(c);","handlingStrategy":"validation","validationCode":"if (entity.getId() == null) {\n    throw new IllegalArgumentException(\"id must be assigned before persist() for \" + entity.getClass().getName());\n}\nem.persist(entity);","typeGuard":"static boolean hasAssignedId(Customer c) {\n    return c != null && c.getId() != null;\n}","tryCatchPattern":"try {\n    em.persist(entity);\n} catch (IdentifierGenerationException e) {\n    // message contains 'must be manually assigned'\n    throw new IllegalArgumentException(\"persist called without an assigned id\", e);\n}","preventionTips":["Create entities only through factory methods that require the id","Add @GeneratedValue when the database should generate the id","For composite ids, verify every attribute is set before persist","Assert non-null ids in save-path unit tests"],"tags":["identifier-generation","assigned-id","persist","jpa"],"backgroundTag":"missing-identifier-before-save","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}