{"record":{"id":"4d3d7ca6702da2a4","repo":"hibernate/hibernate-orm","slug":"illegal-xml-content","errorCode":null,"errorMessage":"Illegal XML content: ","messagePattern":"Illegal XML content: ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/XmlHelper.java","lineNumber":116,"sourceCode":"\t\t\t\t\t\t\tcase 'g':\n\t\t\t\t\t\t\t\tif ( string.charAt( i + 2 ) == 't' && string.charAt( i + 3 ) == ';' ) {\n\t\t\t\t\t\t\t\t\tsb.append( '>' );\n\t\t\t\t\t\t\t\t\ti += 3;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak OUTER;\n\t\t\t\t\t\t\tcase 'q':\n\t\t\t\t\t\t\t\tif ( i + 5 < end\n\t\t\t\t\t\t\t\t\t&& string.charAt( i + 2 ) == 'u'\n\t\t\t\t\t\t\t\t\t&& string.charAt( i + 3 ) == 'o'\n\t\t\t\t\t\t\t\t\t&& string.charAt( i + 4 ) == 't'\n\t\t\t\t\t\t\t\t\t&& string.charAt( i + 5 ) == ';' ) {\n\t\t\t\t\t\t\t\t\tsb.append( '\"' );\n\t\t\t\t\t\t\t\t\ti += 5;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak OUTER;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthrow new IllegalArgumentException( \"Illegal XML content: \" + string.substring( start, end ) );\n\t\t\t\tdefault:\n\t\t\t\t\tsb.append( c );\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn sb.toString();\n\t}\n\n\tprivate static Object fromString(\n\t\t\tEmbeddableMappingType embeddableMappingType,\n\t\t\tString string,\n\t\t\tboolean returnEmbeddable,\n\t\t\tWrapperOptions options,\n\t\t\tint selectableIndex,\n\t\t\tint start,\n\t\t\tint end) throws SQLException {\n\t\tfinal JdbcMapping jdbcMapping = embeddableMappingType.getJdbcValueSelectable( selectableIndex )\n\t\t\t\t.getJdbcMapping();","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/XmlHelper.java#L98-L134","documentation":"XmlHelper.unescape understands only the five named XML entities (&lt; &amp; &apos; &gt; &quot;). When Hibernate reads an XML-mapped aggregate column, any other ampersand sequence in the text content fails entity matching and throws IllegalArgumentException with the offending content. This includes numeric character references, HTML-only entities, and bare '&' characters.","triggerScenarios":"Reading an XML aggregate (XmlJdbcType / SqlTypes.SQLXML mapping) whose stored text contains an ampersand sequence outside the five supported entities, e.g. '&#65;', '&nbsp;', '&#x41;', or an unescaped '&' followed by a character other than l/a/g/q; also an entity truncated at the end of the content region.","commonSituations":"Rows written by another application, ETL job, or script that used broader XML/HTML escaping; hand-edited column values; data migrated from standard XML documents into a Hibernate XML aggregate column.","solutions":["Repair the stored data: replace unsupported entities with the literal character and escape stray '&' as '&amp;'.","Write XML aggregate values only through Hibernate so escaping stays consistent.","Add an ingest-time sanitizer if external writers must touch the column.","Audit the column for suspicious '&' rows before switching reads to Hibernate."],"exampleFix":"-- PostgreSQL audit + fix\n-- before: content holds '&nbsp;' or '&#65;'\nUPDATE t SET doc = REPLACE(doc, '&nbsp;', ' ') WHERE doc LIKE '%&nbsp;%';\nSELECT id FROM t WHERE doc ~ '&(?!amp;|lt;|gt;|apos;|quot;)' AND doc LIKE '%<e>%';","handlingStrategy":"try-catch","validationCode":"static boolean hasOnlySupportedEntities(String content) {\n    return content == null || !content.matches(\"(?s).*&(?!(amp|lt|gt|apos|quot);).*\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    return session.find(Person.class, id); // materializes the XML aggregate\n} catch (IllegalArgumentException ex) {\n    if (ex.getMessage() != null && ex.getMessage().startsWith(\"Illegal XML content\")) {\n        quarantine(id, ex.getMessage());   // log PK + offending content, schedule repair\n        return null;\n    }\n    throw ex;\n}","preventionTips":["Let Hibernate be the only writer of XML aggregate columns.","Sanitize inbound XML data (escape stray '&' as '&amp;', resolve numeric/HTML entities) at ingest.","Audit columns for unsupported entities before enabling Hibernate reads."],"tags":["hibernate","xml","xml-aggregate","entity-escaping","data-corruption"],"backgroundTag":"malformed-xml-data","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}