hibernate/hibernate-orm · error · ClassCastException

session is not an EventSource

Error message

session is not an EventSource

What it means

SharedSessionContractImplementor.asEventSource() is the typed view of a session used by Hibernate's event/listener pipeline and ActionQueue; only the stateful SessionImpl (and delegators wrapping it) override the default, which throws ClassCastException('session is not an EventSource'). A StatelessSession therefore cannot act as an EventSource.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/engine/spi/SharedSessionContractImplementor.java:513

	 * <p>
	 * Only stateful session are sources of events. If this object is
	 * a stateless session, this method return {@code false}.
	 */
	default boolean isEventSource() {
		return false;
	}

	/**
	 * Cast this session to {@link EventSource} if possible.
	 * <p>
	 * Only stateful session are sources of events. If this object is
	 * a stateless session, this method throws.
	 *
	 * @throws ClassCastException if the cast is not possible
	 */
	@Nonnull
	default EventSource asEventSource() {
		throw new ClassCastException( "session is not an EventSource" );
	}

	/**
	 * Whether the session {@linkplain StatelessSessionImplementor stateless}, as opposed tp
	 * {@linkplain SessionImplementor stateful}.
	 *
	 * @apiNote Essentially, whether casting this session to {@linkplain StatelessSessionImplementor} will succeed.
	 */
	default boolean isStateless() {
		return false;
	}

	/**
	 * Called after each operation on a {@link org.hibernate.ScrollableResults},
	 * providing an opportunity for a stateless session to clear its
	 * temporary persistence context. For a stateful session, this method
	 * does nothing.
	 */

View on GitHub (pinned to fad1729dce)

Solutions

  1. Use a regular stateful Session for code paths that need the event pipeline / ActionQueue
  2. Branch first: check session.isStateless() (or session instanceof EventSource) before casting
  3. Avoid StatelessSession features that internally require an ActionQueue (e.g. cascading version increments, listener-driven cascades) or restructure them as explicit operations

Example fix

// before
EventSource src = (EventSource) session; // or session.asEventSource() on a StatelessSession -> ClassCastException

// after
if (session.isStateless()) {
    throw new UnsupportedOperationException("this operation needs a stateful Session");
}
EventSource src = session.asEventSource();
Defensive patterns

Strategy: type-guard

Validate before calling

if (sharedSession.isStateless()) {
    throw new UnsupportedOperationException("Operation requires a stateful Session (EventSource)");
}

Type guard

static boolean canActAsEventSource(SharedSessionContractImplementor s) {
    return !s.isStateless(); // equivalent to: s instanceof EventSource
}

Prevention

When it happens

Trigger: Calling asEventSource() on a StatelessSession directly, or reaching internal code that does — bulk operation cleanup (BulkOperationCleanupAction), version increments, natural-id resolution callbacks, session event construction (AbstractSessionEvent), and result-set processing all call session.asEventSource() and fail on a stateless session.

Common situations: Batch jobs written against StatelessSession hitting features that assume a stateful session (action queue, event listeners, cascade via events, Envers-style integrations); user utilities casting SharedSessionContractImplementor to EventSource; mixing session types behind a shared interface.

Related errors


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