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
- If null elements are not needed, change the field type to byte[]/char[] (recommended)
- If wrapper semantics are wanted, set hibernate.type.wrapper_array_handling=allow
- To keep pre-6.2 behavior during migration, set hibernate.type.wrapper_array_handling=legacy
- 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
- Model binary data as byte[], never Byte[]
- Set hibernate.type.wrapper_array_handling explicitly (allow or legacy) before upgrading to 6.2+
- Run the wrapper-array scan in CI when planning a Hibernate upgrade
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
- Property '" + qualify( getEntityName(), prop.getName() ) + "
- Injection of parent instance into embeddable result is not p
- Unable to determine JDBC type for converted parameter relati
- Basic array has element type '" + componentJavaType.getTypeN
- WRITE is not a valid LockMode as an argument
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/f8504033120f11d8.
Report an issue: GitHub.