hibernate/hibernate-orm · error · HibernateException

Audit graph mutation plan used with non-graph action queue

Error message

Audit graph mutation plan used with non-graph action queue

What it means

AuditCollectionMutationPlanContributor supplies the mutation plan used to audit/temporal-track collection changes, and it needs to register its results on a GraphBasedActionQueue (resolveCollector, AuditCollectionMutationPlanContributor.java:100). If the session's ActionQueue is the legacy implementation (session.getActionQueue() not instanceof GraphBasedActionQueue), it throws HibernateException("Audit graph mutation plan used with non-graph action queue"). The audit/temporal extension and the flush-queue configuration are out of sync: the plan is active but the queue it targets is disabled.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/action/queue/internal/decompose/collection/AuditCollectionMutationPlanContributor.java:100

			SessionImplementor session) {
		final var persistenceContext = session.getPersistenceContextInternal();
		final var collectionEntry = persistenceContext.getCollectionEntry( collection );
		if ( collectionEntry != null && collectionEntry.getLoadedPersister() != null ) {
			return collection.getStoredSnapshot();
		}
		else if ( collection instanceof PersistentArrayHolder<?> ) {
			final var oldCollection = persistenceContext.getCollection( new CollectionKey( persister, id ) );
			return oldCollection != null ? oldCollection.getStoredSnapshot() : null;
		}
		return null;
	}

	private GraphBasedActionQueue resolveCollector(SessionImplementor session) {
		final var actionQueue = session.getActionQueue();
		if ( actionQueue instanceof GraphBasedActionQueue graphBasedActionQueue ) {
			return graphBasedActionQueue;
		}
		throw new HibernateException( "Audit graph mutation plan used with non-graph action queue" );
	}
}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Remove the legacy override or set hibernate.flush.queue.type=graph - the graph queue is the 8.x default and what audit plans require
  2. Verify no programmatic configuration sets a legacy ActionQueueFactory (ActionQueueFactoryService QueueType.LEGACY)
  3. Keep the audit/temporal feature configuration and the flush queue setting in the same config source so they cannot drift
  4. If legacy queue is mandatory for you, disable the audit/graph mutation plan contributor until it supports the legacy queue

Example fix

# before - conflicting settings: audit plans need the graph queue
hibernate.flush.queue.type=legacy
hibernate.audit.enabled=true

# after - align on the graph queue
hibernate.flush.queue.type=graph
hibernate.audit.enabled=true
Defensive patterns

Strategy: validation

Validate before calling

// fail fast at startup if audit plans are on but the queue type is legacy
String queueType = configuration.getSettings()
        .getOrDefault("hibernate.flush.queue.type", "graph").toString();
if (auditEnabled && "legacy".equals(queueType)) {
    throw new IllegalStateException(
        "audit collection plans require the graph action queue: remove hibernate.flush.queue.type=legacy");
}

Prevention

When it happens

Trigger: Registering audit/temporal collection mutation plan contributors while hibernate.flush.queue.type=legacy is set (FlushSettings.FLUSH_QUEUE_TYPE); a session type or factory configuration that forces ActionQueueLegacy (e.g. legacy setting in persistence.xml, or an old default carried over from pre-8 config files) while audit plans are on the classpath/enabled.

Common situations: Upgrading to Hibernate 8 keeping an explicit hibernate.flush.queue.type=legacy for compatibility, while enabling the audit/history feature that assumes the new default graph queue; mixed configuration across microservice instances; environment-specific property overrides drifting apart.

Related errors


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