hibernate/hibernate-orm · error · InvalidObjectException

Could not find a SessionFactory [uuid={},name={}]

Error message

Could not find a SessionFactory [uuid={},name={}]

What it means

SqmCriteriaNodeBuilder implements Serializable and resolves itself on deserialization via SessionFactoryRegistry, first by stored UUID then by factory name. If neither lookup finds a live SessionFactory in the current JVM, readResolve throws InvalidObjectException. This is by design: a node builder is meaningless without its factory's query engine, so deserialization must reattach to a registered factory.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java:3675

	private static SessionFactory locateSessionFactoryOnDeserialization(String uuid, String name) throws InvalidObjectException{
		final SessionFactory uuidResult = SessionFactoryRegistry.INSTANCE.getSessionFactory( uuid );
		if ( uuidResult != null ) {
			CORE_LOGGER.tracef( "Resolved SessionFactory by UUID [%s]", uuid );
			return uuidResult;
		}

		// in case we were deserialized in a different JVM, look for an instance with the same name
		// (provided we were given a name)
		if ( name != null ) {
			final SessionFactory namedResult = SessionFactoryRegistry.INSTANCE.getNamedSessionFactory( name );
			if ( namedResult != null ) {
				CORE_LOGGER.tracef( "Resolved SessionFactory by name [%s]", name );
				return namedResult;
			}
		}

		throw new InvalidObjectException( "Could not find a SessionFactory [uuid=" + uuid + ",name=" + name + "]" );
	}

	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Non-standard HQL functions

	@Override
	public <T> SqmFunction<T> sql(String pattern, Class<T> type, Expression<?>... arguments) {
		failIfSafeModeEnabled( safeModeEnabled, "sql", null );
		final List<SqmExpression<?>> sqmArguments = new ArrayList<>( expressionList( arguments ) );
		sqmArguments.add( 0, literal( pattern ) );
		return getFunctionDescriptor( "sql" ).generateSqmExpression(
				sqmArguments,
				getTypeConfiguration().standardBasicTypeForJavaType( type ),
				queryEngine
		);
	}

	@Override

View on GitHub (pinned to fad1729dce)

Solutions

  1. Give the SessionFactory a stable name before building it: cfg.setProperty(AvailableSettings.SESSION_FACTORY_NAME, "main") (and SESSION_FACTORY_NAME_IS_JNDI=false if you don't use JNDI) so other JVMs can resolve by name.
  2. Ensure the receiving JVM has fully built (and not yet closed) the SessionFactory before deserializing.
  3. Avoid serializing criteria trees at all: ship the HQL string or the TypedQueryReference and rebuild the criteria on the remote side.

Example fix

// before
StandardServiceRegistry ssr = new StandardServiceRegistryBuilder().build();
SessionFactory sf = new MetadataBuilderImpl... .buildSessionFactory(); // no name: only uuid resolvable in THIS jvm
Object o = deserialize(bytesFromOtherNode); // InvalidObjectException

// after
StandardServiceRegistry ssr = new StandardServiceRegistryBuilder()
        .applySetting(AvailableSettings.SESSION_FACTORY_NAME, "main")
        .applySetting(AvailableSettings.SESSION_FACTORY_NAME_IS_JNDI, "false")
        .build();
// build + open the factory on the receiving node BEFORE deserialize(bytes);
Defensive patterns

Strategy: fallback

Validate before calling

// On the receiving JVM, ensure a resolvable factory exists BEFORE deserializing
if (SessionFactoryRegistry.INSTANCE.getNamedSessionFactory("main") == null) {
    throw new IllegalStateException("Build the named SessionFactory 'main' before deserializing criteria");
}

Try / catch

try (ObjectInputStream in = new ObjectInputStream(bytes)) {
    return in.readObject();
} catch (InvalidObjectException e) {
    // factory not registered here: rebuild it (by name) and retry, or reconstruct criteria from HQL
    ensureSessionFactoryStarted();
    return deserializeAgain(bytes);
}

Prevention

When it happens

Trigger: Deserializing a criteria tree (or the builder itself) in a JVM/process where the SessionFactory that created it was closed, was never built, or was built without a name; sending serialized criteria over the wire (caches, messaging) to a node that has not started Hibernate; serializing into a session bean pool and deserializing after factory close.

Common situations: Distributed setups (Ignite/Coherence/JGroups) that replicate criteria objects; storing criteria queries in a serialized HTTP session and restoring after a restart where the factory name/uuid differs; unit tests that deserialize fixtures without booting a SessionFactory.

Related errors


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