hibernate/hibernate-orm · error · IllegalArgumentException
Illegal XML for array:
Error message
Illegal XML for array:
What it means
XmlHelper.arrayFromString handles the read path for XML array attributes. It requires the column value to be <Collection> ... </Collection>, or <Collection/> for an empty array. Any other content throws IllegalArgumentException 'Illegal XML for array'.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/XmlHelper.java:324
return (X) instantiate( embeddableMappingType, attributeValues );
}
//noinspection unchecked
return (X) array;
}
public static <X> X arrayFromString(
JavaType<X> javaType,
XmlArrayJdbcType xmlArrayJdbcType,
String string,
WrapperOptions options) throws SQLException {
if ( string == null ) {
return null;
}
else if ( EMPTY_COLLECTION_TAG.equals( string ) ) {
return javaType.wrap( Collections.emptyList(), options );
}
else if ( !string.startsWith( COLLECTION_START_TAG ) || !string.endsWith( COLLECTION_END_TAG ) ) {
throw new IllegalArgumentException( "Illegal XML for array: " + string );
}
final JavaType<?> elementJavaType = ((BasicPluralJavaType<?>) javaType).getElementJavaType();
final Class<?> preferredJavaTypeClass = xmlArrayJdbcType.getElementJdbcType().getPreferredJavaTypeClass( options );
final JavaType<?> jdbcJavaType;
if ( preferredJavaTypeClass == null || preferredJavaTypeClass == elementJavaType.getJavaTypeClass() ) {
jdbcJavaType = elementJavaType;
}
else {
jdbcJavaType = options.getTypeConfiguration().getJavaTypeRegistry().resolveDescriptor( preferredJavaTypeClass );
}
final ArrayList<Object> arrayList = new ArrayList<>();
final int end = fromArrayString(
string,
true,
options,
COLLECTION_START_TAG.length(),
arrayList,
elementJavaType,View on GitHub (pinned to fad1729dce)
Solutions
- Rewrite stored array values into <Collection>...</Collection> form (empty array exactly '<Collection/>').
- Write array values through Hibernate so the wrapper is always emitted.
- Check the attribute actually maps to XmlArrayJdbcType and the element type matches the stored elements.
Defensive patterns
Strategy: validation
Validate before calling
static boolean isHibernateAggregateArrayXml(String s) {
return s == null || "<Collection/>".equals(s)
|| (s.startsWith("<Collection>") && s.endsWith("</Collection>"));
} Try / catch
try {
return session.find(Person.class, id);
} catch (IllegalArgumentException ex) {
if (ex.getMessage() != null && ex.getMessage().startsWith("Illegal XML for array")) {
quarantine(id, ex.getMessage());
return null;
}
throw ex;
} Prevention
- Map XML array attributes only to columns written by Hibernate itself.
- Store empty arrays as '<Collection/>' and NULLs as NULL in migration scripts.
- Add a column-format check to deployment smoke tests.
When it happens
Trigger: Reading an attribute mapped with XmlArrayJdbcType (e.g. @Array / basic-array mapping on an XML column) whose stored value is not wrapped in the <Collection> tags: bare values, a different root element, or a plain empty string instead of <Collection/>.
Common situations: Array data written by an external tool or earlier Hibernate version; switching a column between scalar and array aggregate mappings; empty-string defaults on NOT NULL columns.
Related errors
- XML not properly formatted:
- Duplicate collection definition '%s'
- Could not instantiate named strategy class [%s]
- Unexpected node type -
- Could not locate root element
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/a4db4fbcbbad2e95.
Report an issue: GitHub.