hibernate/hibernate-orm · error · HibernateException

Array element type error

Error message

Array element type error

What it means

For <array>/<primitive-array> mappings, getSnapshot deep-copies every element into a fresh array of the mapped element class via persister.getElementType().deepCopy. If a copied value cannot be stored into that array (IllegalArgumentException from Array.set), Hibernate wraps it as 'Array element type error': the runtime type produced by the element type does not fit the array component type declared in the mapping.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentArrayHolder.java:86

	 */
	public PersistentArrayHolder(SharedSessionContractImplementor session, CollectionPersister persister) {
		super( session );
		elementClass = persister.getElementClass();
	}

	@Override
	public Serializable getSnapshot(CollectionPersister persister) throws HibernateException {
//		final int length = (array==null) ? tempList.size() : Array.getLength( array );
		final int length = getLength( array );
		final var result = (Serializable) newInstance( persister.getElementClass(), length );
		for ( int i=0; i<length; i++ ) {
//			final Object elt = (array==null) ? tempList.get( i ) : Array.get( array, i );
			final Object elt = get( array, i );
			try {
				set( result, i, persister.getElementType().deepCopy( elt, persister.getFactory() ) );
			}
			catch (IllegalArgumentException iae) {
				throw new HibernateException( "Array element type error", iae );
			}
		}
		return result;
	}

	@Override
	public boolean isSnapshotEmpty(Serializable snapshot) {
		return getLength( snapshot ) == 0;
	}

	@Override
	public Collection<E> getOrphans(Serializable snapshot, String entityName) throws HibernateException {
		//noinspection unchecked
		final E[] sn = (E[]) snapshot;
		final Object[] arr = (Object[]) array;
		if ( arr.length == 0 ) {
			return Arrays.asList( sn );
		}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Align the mapping's element-type and element-class with the actual array component type
  2. Make custom UserType.deepCopy return the same class it received (a faithful copy)
  3. Replace exotic array mappings with @ElementCollection on a List field where possible
  4. Add a round-trip test that loads, snapshots, and re-saves the array collection

Example fix

<!-- before: element type mismatch -->
<array name="scores" element-class="java.lang.Integer">
    <element type="java.lang.Double"/>
</array>

<!-- after: consistent element type -->
<array name="scores" element-class="java.lang.Double">
    <element type="java.lang.Double"/>
</array>
Defensive patterns

Strategy: type-guard

Validate before calling

if (array != null && array.length > 0) {
    Class<?> component = array.getClass().getComponentType();
    Class<?> mapped = persister.getElementClass();
    if (!mapped.isAssignableFrom(component)) {
        throw new IllegalStateException("Array component " + component.getName()
                + " incompatible with mapped element class " + mapped.getName());
    }
}

Type guard

static boolean elementTypeMatches(Object[] arr, Class<?> mappedElementClass) {
    return arr == null || arr.length == 0
            || mappedElementClass.isAssignableFrom(arr.getClass().getComponentType());
}

Prevention

When it happens

Trigger: An <array> mapping whose element-type/element-class does not match the Java array's component type; a custom UserType whose deepCopy returns a different class than the values it receives; changing the entity field type without updating the mapping.

Common situations: Custom value types with sloppy deepCopy contracts; legacy hbm.xml array mappings after refactors; primitive vs wrapper type mismatches.

Related errors


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