hibernate/hibernate-orm · error · TransientObjectException

Cannot delete instance of entity '${persister.getEntityName(

Error message

Cannot delete instance of entity '${persister.getEntityName()}' because it has a null identifier

What it means

On the native-bootstrap delete path for detached entities, deleteDetachedEntity() reads the identifier and finds null — the object is transient, not detached, so there is nothing to delete by. Hibernate throws TransientObjectException('Cannot delete instance of entity ... because it has a null identifier').

Source

Thrown at hibernate-core/src/main/java/org/hibernate/event/internal/DefaultDeleteEventListener.java:169

			deleteTransientEntity( source, entity, persister, transientEntities );
		}
		else {
			deleteDetachedEntity( event, transientEntities, entity, persister, source );
		}
	}

	private void deleteDetachedEntity(
			@Nonnull DeleteEvent event,
			@Nonnull DeleteContext transientEntities,
			@Nonnull Object entity,
			@Nonnull EntityPersister persister,
			@Nonnull EventSource source) {
		if ( source.getFactory().getSessionFactoryOptions().isJpaBootstrap() ) {
			throw new DetachedObjectException( "Given entity is not associated with the persistence context" );
		}
		final Object id = persister.getIdentifier( entity, source );
		if ( id == null ) {
			throw new TransientObjectException( "Cannot delete instance of entity '"
					+ persister.getEntityName() + "' because it has a null identifier" );
		}

		final var key = source.generateEntityKey( id, persister);
		final Object version = persister.getVersion( entity );

//		persistenceContext.checkUniqueness( key, entity );
		if ( !flushAndEvictExistingEntity( key, version, persister, source ) ) {

			new OnUpdateVisitor( source, id, entity ).process( entity, persister );

			final var entityEntry =
					source.getPersistenceContextInternal()
							.addEntity(
									entity,
									persister.isMutable() ? Status.MANAGED : Status.READ_ONLY,
									persister.getValues( entity ),
									key,

View on GitHub (pinned to fad1729dce)

Solutions

  1. Null-check the identifier before calling delete/remove
  2. If the id is absent, treat it as a no-op or a validation error rather than calling Hibernate
  3. Delete by id with a JPQL mutation query when you only have the key
  4. Fix the id mapping/getter if the row exists in the database but the entity reads null

Example fix

// before
session.remove(customer); // customer.id == null -> TransientObjectException

// after
if (customer.getId() != null) {
    session.remove(customer);
}
// or delete by id
session.createMutationQuery("delete from Customer c where c.id = :id")
       .setParameter("id", id)
       .executeUpdate();
Defensive patterns

Strategy: validation

Validate before calling

if (customer.getId() == null) {
    throw new IllegalArgumentException("cannot delete a transient " + Customer.class.getSimpleName());
}
session.remove(customer);

Type guard

static boolean isDeletable(Customer c) {
    return c != null && c.getId() != null;
}

Prevention

When it happens

Trigger: session.remove/delete(new Customer()) on an object that was never saved; entity whose id getter returns null because the mapping reads the wrong field or the id was reset; deleting an object whose identifier was never populated by the assembler.

Common situations: Delete handlers receiving empty request payloads that map to fresh instances; id field nulled during DTO copying; entities with application-assigned ids that were never set before delete.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/742b55164ba7c1d4. Report an issue: GitHub.