hibernate/hibernate-orm · error · IllegalArgumentException
XML not properly formed:
Error message
XML not properly formed:
What it means
Tail of XmlHelper's generic fromString parser: the scan loop reached the end of the string while still inside an element, meaning the closing tag was never found. The stored XML aggregate content is truncated or unterminated.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/XmlHelper.java:425
}
break;
case '/':
if ( tagName == null ) {
// A shorthand tag encodes null
values.add( null );
// skip the closing angle bracket
i++;
tagNameStart = -1;
assert string.charAt( i ) == '>';
}
else {
// This must be a char in the content
assert contentStart != -1;
}
break;
}
}
throw new IllegalArgumentException( "XML not properly formed: " + string.substring( start ) );
}
private static int fromString(
EmbeddableMappingType embeddableMappingType,
String string,
boolean returnEmbeddable,
WrapperOptions options,
Object[] values,
int start) throws SQLException {
int tagNameStart = -1;
int contentStart = -1;
String tagName = null;
for ( int i = start; i < string.length(); i++ ) {
final char c = string.charAt( i );
switch ( c ) {
case '<':
if ( tagNameStart == -1 ) {
if ( string.charAt( i + 1 ) == '/' ) {View on GitHub (pinned to fad1729dce)
Solutions
- Identify affected rows with a SQL audit (content not ending in the expected closing tag).
- Repair or null the truncated rows, then re-write them through Hibernate.
- Enlarge the column type (e.g. CLOB/XML type) so writes never truncate again.
Defensive patterns
Strategy: try-catch
Try / catch
try {
return session.find(Person.class, id);
} catch (IllegalArgumentException ex) {
if (ex.getMessage() != null && ex.getMessage().startsWith("XML not properly formed")) {
// truncated row: log PK and raw column value for repair
logTruncated(id, ex.getMessage());
return null;
}
throw ex;
} Prevention
- Use unbounded column types (CLOB / native XML) for aggregate columns.
- Audit for rows not ending in the expected closing tag after bulk loads.
- Write aggregates atomically through Hibernate transactions, not scripts.
When it happens
Trigger: Reading an XML aggregate whose content ends before the closing tag: column truncation (VARCHAR too short), partial writes after a crash, or manual edits that removed tags.
Common situations: Column length changed or too small for large aggregates; non-atomic updates by scripts; data truncation during ETL between databases.
Related errors
- Illegal XML content:
- XML not properly formatted:
- XML starts sub-object for a non-aggregate type at index %d.
- Support for attribute mapping type not yet implemented:
- Could not find selectable [%s] in embeddable type [%s] for X
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/ad2e33fbb088c682.
Report an issue: GitHub.