hibernate/hibernate-orm · error · HibernateException

Attempt to load entity from cache using provided object inst

Error message

Attempt to load entity from cache using provided object instance, but cache is storing references: {}

What it means

The second-level cache stores either a disassembled CacheEntry or, when reference caching is enabled, a ReferenceCacheEntryImpl holding the entity instance itself. When a cached lookup finds a reference entry but the load was given an existing instance to populate (instanceToLoad != null), Hibernate throws, because a shared cached reference cannot be written into a caller-provided object.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/loader/internal/CacheLoadHelper.java:184

			}
			else {
				statistics.entityCacheHit( rootEntityRole, regionName );
			}
		}
		return cacheEntry;
	}

	private static Object processCachedEntry(
			final Object instanceToLoad,
			final EntityPersister persister,
			final Object cacheEntry,
			final SharedSessionContractImplementor source,
			final EntityKey entityKey) {
		final var entry = (CacheEntry)
				persister.getCacheEntryStructure().destructure( cacheEntry, source.getFactory() );
		if ( entry.isReferenceEntry() ) {
			if ( instanceToLoad != null ) {
				throw new HibernateException( "Attempt to load entity from cache using provided object instance, "
						+ "but cache is storing references: " + entityKey.getIdentifier() );
			}
			else {
				return convertCacheReferenceEntryToEntity( (ReferenceCacheEntryImpl) entry, source, entityKey );
			}
		}
		else {
			final Object entity =
					convertCacheEntryToEntity(
							entry,
							entityKey.getIdentifier(),
							source,
							persister,
							instanceToLoad,
							entityKey
					);
			if ( entity == null ) {
				return null;

View on GitHub (pinned to fad1729dce)

Solutions

  1. Remove hibernate.cache.use_reference_entries=true so the cache stores normal disassembled entries (default false).
  2. Avoid load-with-instance calls (two-arg load, refresh into an instance) for entities cached with reference entries; use plain byId loads.
  3. If reference caching must stay, keep those entities immutable and route all access through instance-free loads.

Example fix

// before
props.put(AvailableSettings.USE_DIRECT_REFERENCE_CACHE_ENTRIES, true);
// ...
session.load(userId, existingUser); // load-with-instance conflicts with reference entries

// after: reference entries disabled (default)
User u = session.byId(User.class).load(userId);
Defensive patterns

Strategy: fallback

Validate before calling

if ( sessionFactory.getSessionFactoryOptions().isDirectReferenceCacheEntriesEnabled() ) {
    // do not pass instances into load/refresh for cached entities
    return session.byId( entityClass ).load( id );
}

Try / catch

try {
    session.refresh( instance );
}
catch ( org.hibernate.HibernateException e ) {
    if ( e.getMessage() != null && e.getMessage().contains( "cache is storing references" ) ) {
        // fall back to a plain load and copy state manually
    }
    else {
        throw e;
    }
}

Prevention

When it happens

Trigger: hibernate.cache.use_reference_entries=true (AvailableSettings.USE_DIRECT_REFERENCE_CACHE_ENTRIES) combined with a load path that supplies an instance: two-arg session.load(id, instance), refresh into a provided instance, or a custom loader/event listener that sets an instance on the load event; the entity is immutable and cached.

Common situations: Enabling reference entries to speed up immutable entities and later calling load/refresh with a provided instance; Hibernate 5-to-6 migration where reference-cache-entry handling changed; custom event listeners injecting instances into LoadEvent.

Related errors


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