hibernate/hibernate-orm · error · ClassCastException

Provided key does not support instance identity

Error message

Provided key does not support instance identity

What it means

InstanceIdentityMap addresses entries by an integer instance id injected by Hibernate bytecode enhancement ($$_hibernate_getInstanceId from the InstanceIdentity interface). The java.util.Map-compatibility overload containsKey(Object) only works when the passed key implements InstanceIdentity; any other object (an id value, an unenhanced POJO, a String) is rejected with ClassCastException rather than returning a wrong answer.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/internal/util/collections/InstanceIdentityMap.java:74

	 * @return {@code true} if this map contains a mapping for the specified instance id
	 * @implNote This method accesses the backing array with the provided instance id, but performs an instance
	 * equality check ({@code ==}) with the provided key to ensure it corresponds to the mapped one
	 */
	public boolean containsKey(int instanceId, Object key) {
		return get( instanceId, key ) != null;
	}

	/**
	 * {@inheritDoc}
	 * @implNote This only works for {@link InstanceIdentity} keys, and it's inefficient
	 * since we need to do a type check. Prefer using {@link #containsKey(int, Object)}.
	 */
	@Override
	public boolean containsKey(Object key) {
		if ( key instanceof InstanceIdentity instance ) {
			return containsKey( instance.$$_hibernate_getInstanceId(), instance );
		}
		throw new ClassCastException( "Provided key does not support instance identity" );
	}

	@Override
	public boolean containsValue(Object value) {
		for ( V v : values() ) {
			if ( Objects.equals( value, v ) ) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Tests if the specified key-value mapping is in the map.
	 *
	 * @param key possible key, must be an instance of {@link InstanceIdentity}
	 * @param value possible value
	 * @return {@code true} if and only if the specified key-value mapping is in the map

View on GitHub (pinned to fad1729dce)

Solutions

  1. Probe with the entity instance itself, and the same managed instance the map holds
  2. Prefer the id-based overload containsKey(int instanceId, Object key)
  3. Ensure the entity is bytecode-enhanced if you must use instance-identity collections
  4. If you do not need identity addressing, use a plain HashMap keyed by business id

Example fix

// before: probing with a database id
boolean loaded = map.containsKey( orderId );
// after: probe with the enhanced entity instance
boolean loaded = order instanceof InstanceIdentity i
        ? map.containsKey( i.$$_hibernate_getInstanceId(), order )
        : false;
Defensive patterns

Strategy: type-guard

Type guard

static boolean usableAsInstanceIdentityKey(Object key) {
    return key instanceof org.hibernate.engine.spi.InstanceIdentity;
}

Prevention

When it happens

Trigger: instanceIdentityMap.containsKey(someId) where someId is a String/Long/database id; containsKey(entityInstance) where the entity class was not bytecode-enhanced; passing a detached copy or a different object than the managed instance.

Common situations: Treating persistence-context-internal maps as ordinary Maps and probing them with identifiers instead of entity instances; using entity classes with enhancement disabled (plain POJOs never implement InstanceIdentity).

Related errors


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