hibernate/hibernate-orm · error · MappingException

The property %s.%s uses a wrapper type Byte[]/Character[] wh

Error message

The property %s.%s uses a wrapper type Byte[]/Character[] which indicates an issue in your domain model. These types have been treated like byte[]/char[] until Hibernate 6.2 which meant that null elements were not allowed, but on JDBC were processed like VARBINARY or VARCHAR. If you don't use nulls in your arrays, change the type of the property to byte[]/char[]. To allow explicit uses of the types Byte[]/Character[], allowing null elements, but with a different serialization format than before Hibernate 6.2, configure the setting '%s' to the value '%s'. To revert to the legacy treatment of these types, configure the value to '%s'. For more information on this matter, consult the migration guide of Hibernate 6.2 and the Javadoc of the field 'org.hibernate.cfg.AvailableSettings.WRAPPER_ARRAY_HANDLING'.

What it means

Hibernate 6.2 changed how Byte[] and Character[] (wrapper arrays) are treated: before 6.2 they behaved like byte[]/char[] (no null elements, processed as VARBINARY/VARCHAR on JDBC); 6.2 gives them distinct semantics. When a property uses one of these types under the default handling, Property.isValid() throws this MappingException telling you to migrate to the primitive array or pick an explicit mode via the hibernate.type.wrapper_array_handling setting.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/mapping/Property.java:321

			|| BASIC.getExternalName().equals( propertyAccessorName );
	}

	public Map<String, MetaAttribute> getMetaAttributes() {
		return metaAttributes;
	}

	public MetaAttribute getMetaAttribute(String attributeName) {
		return metaAttributes==null ? null : metaAttributes.get(attributeName);
	}

	public void setMetaAttributes(Map<String, MetaAttribute> metas) {
		this.metaAttributes = metas;
	}

	public boolean isValid(MappingContext mappingContext) throws MappingException {
		final Value value = getValue();
		if ( value instanceof BasicValue basicValue && basicValue.isDisallowedWrapperArray() ) {
			throw new MappingException(
					"""
					The property %s.%s uses a wrapper type Byte[]/Character[] which indicates an issue in your domain model. \
					These types have been treated like byte[]/char[] until Hibernate 6.2 which meant that null elements were \
					not allowed, but on JDBC were processed like VARBINARY or VARCHAR. If you don't use nulls in your arrays, \
					change the type of the property to byte[]/char[]. To allow explicit uses of the types Byte[]/Character[], \
					allowing null elements, but with a different serialization format than before Hibernate 6.2, configure \
					the setting '%s' to the value '%s'. To revert to the legacy treatment of these types, configure the value to '%s'. \
					For more information on this matter, consult the migration guide of Hibernate 6.2 and the Javadoc of the \
					field 'org.hibernate.cfg.AvailableSettings.WRAPPER_ARRAY_HANDLING'.\
					"""
							.formatted( persistentClass.getEntityName(), name, WRAPPER_ARRAY_HANDLING,
									WrapperArrayHandling.ALLOW, WrapperArrayHandling.LEGACY )
			);
		}
		return value.isValid( mappingContext );
	}

	public String toString() {

View on GitHub (pinned to fad1729dce)

Solutions

  1. If null elements are not needed, change the field type to byte[]/char[] (recommended)
  2. If wrapper semantics are wanted, set hibernate.type.wrapper_array_handling=allow
  3. To keep pre-6.2 behavior during migration, set hibernate.type.wrapper_array_handling=legacy
  4. Consult the Hibernate 6.2 migration guide and the javadoc of AvailableSettings.WRAPPER_ARRAY_HANDLING

Example fix

// before
@Entity class Document { @Column(name = "payload") Byte[] payload; }

// after
@Entity class Document { @Column(name = "payload") byte[] payload; }
// or keep Byte[] and configure: hibernate.type.wrapper_array_handling=allow
Defensive patterns

Strategy: validation

Validate before calling

// scan entities for wrapper-array fields before upgrading or booting on 6.2+
static List<String> wrapperArrayFields(Class<?>... entities) {
    List<String> hits = new ArrayList<>();
    for (Class<?> e : entities)
        for (Field f : e.getDeclaredFields())
            if (f.getType() == Byte[].class || f.getType() == Character[].class)
                hits.add(e.getSimpleName() + '.' + f.getName());
    return hits; // empty means this change cannot bite you
}

Type guard

static boolean isWrapperArrayField(Field f) {
    return f.getType() == Byte[].class || f.getType() == Character[].class;
}

Prevention

When it happens

Trigger: An entity field of type Byte[] or Character[] (not byte[]/char[]) with no explicit wrapper-array handling configured; upgrading an application from Hibernate 6.1 or earlier to 6.2+; domain models that genuinely need nullable array elements.

Common situations: Hibernate 5.x/6.0/6.1 to 6.2+ upgrades; binary fields accidentally modeled with the boxed wrapper type; code generators emitting Byte[] for binary columns.

Related errors


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