{"record":{"id":"eb4ad48ac862835d","repo":"hibernate/hibernate-orm","slug":"could-not-deserialize-string-to-java-type-eb4ad4","errorCode":null,"errorMessage":"Could not deserialize string to java type: {}","messagePattern":"Could not deserialize string to java type: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/type/format/jackson/JacksonXmlFormatMapper.java","lineNumber":163,"sourceCode":"\t\t\t\t\t);\n\t\t\t\t\treturn javaType.wrap( collectionWrapper.value, wrapperOptions );\n\t\t\t\t}\n\t\t\t\telse if ( javaType.getJavaTypeClass().isArray() ) {\n\t\t\t\t\tfinal CollectionWrapper<?> collectionWrapper = objectMapper.readValue(\n\t\t\t\t\t\t\tcharSequence.toString(),\n\t\t\t\t\t\t\tobjectMapper.constructType( new ParameterizedTypeImpl( CollectionWrapper.class,\n\t\t\t\t\t\t\t\t\tnew Type[] {javaType.getJavaTypeClass().getComponentType()}, null ) )\n\t\t\t\t\t);\n\t\t\t\t\treturn javaType.wrap( collectionWrapper.value, wrapperOptions );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn objectMapper.readValue(\n\t\t\t\t\tcharSequence.toString(),\n\t\t\t\t\tobjectMapper.constructType( javaType.getJavaType() )\n\t\t\t);\n\t\t}\n\t\tcatch (JsonProcessingException e) {\n\t\t\tthrow new IllegalArgumentException( \"Could not deserialize string to java type: \" + javaType, e );\n\t\t}\n\t}\n\n\t@Override\n\tpublic <T> String toString(T value, JavaType<T> javaType, WrapperOptions wrapperOptions) {\n\t\tif ( javaType.getJavaType() == String.class || javaType.getJavaType() == Object.class ) {\n\t\t\treturn (String) value;\n\t\t}\n\t\tif ( !legacyFormat ) {\n\t\t\tif ( Map.class.isAssignableFrom( javaType.getJavaTypeClass() ) ) {\n\t\t\t\tfinal Type keyType;\n\t\t\t\tfinal Type elementType;\n\t\t\t\tif ( javaType.getJavaType() instanceof ParameterizedType parameterizedType ) {\n\t\t\t\t\tkeyType = parameterizedType.getActualTypeArguments()[0];\n\t\t\t\t\telementType = parameterizedType.getActualTypeArguments()[1];\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tkeyType = Object.class;","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/type/format/jackson/JacksonXmlFormatMapper.java#L145-L181","documentation":"JacksonXmlFormatMapper is the FormatMapper Hibernate uses for @JdbcTypeCode(SqlTypes.SQLXML) attributes via jackson-dataformat-xml. This IllegalArgumentException (JacksonXmlFormatMapper.java:163) wraps a JsonProcessingException raised when the stored XML cannot be parsed into the attribute's Java type, including the Map/array paths that depend on the mapper's legacyFormat flag. The stored XML layout for collections and maps changed between Hibernate versions, controlled by hibernate.type.xml_format_mapper.legacy_format.","triggerScenarios":"Loading an entity with a SqlTypes.SQLXML attribute whose column XML is malformed or does not match the attribute type; reading XML written by an older Hibernate version (legacy <Collection><e>... wrapper layout) while running with the new non-legacy default (legacyFormat=false in JacksonXmlFormatMapper.java:58-61); mapping a POJO whose fields do not match the XML element names; attribute types Jackson-XML cannot construct (no default constructor).","commonSituations":"Upgrading Hibernate across the version that introduced the new XML format and reading pre-existing rows; changing the attribute type (List to Map or vice versa) without migrating stored XML; external systems writing the XML column with a different layout.","solutions":["If the data was written by an older Hibernate, set hibernate.type.xml_format_mapper.legacy_format=true so the mapper reads the legacy wrapper layout.","Compare a failing column value against the attribute type and fix the data or the mapping so element names/shape match.","Make the target type Jackson-XML friendly: default constructor, @JacksonXmlProperty/@JacksonXmlRootElement names matching the stored XML.","Migrate stored XML with a one-off script when the attribute type changes.","Supply a customized XmlMapper through JacksonXmlFormatMapper(ObjectMapper, legacyFormat) via the hibernate.type.xml_format_mapper setting if you need bespoke handling."],"exampleFix":"// before - rows written by old Hibernate fail to read after upgrade\n<persistence ...>\n  <properties>\n    <property name=\"hibernate.type.xml_format_mapper\" value=\"jackson-xml\"/>\n  </properties>\n\n// after - opt into the legacy XML layout for pre-upgrade data\n<property name=\"hibernate.type.xml_format_mapper.legacy_format\" value=\"true\"/>","handlingStrategy":"try-catch","validationCode":"// After a Hibernate upgrade, sample existing rows and check they parse\nXmlMapper xml = XmlMapper.builder().findAndAddModules().build();\nfor ( String storedXml : sampleColumnValues() ) {\n    xml.readValue( storedXml, MyXmlType.class ); // throws early with a clear location\n}","typeGuard":null,"tryCatchPattern":"try {\n    return session.find( Doc.class, id );\n} catch ( IllegalArgumentException e ) {\n    if ( e.getCause() instanceof com.fasterxml.jackson.core.JsonProcessingException jpe ) {\n        // stored XML does not match attribute type / format version - check jpe.getLocation()\n    } else throw e;\n}","preventionTips":["Set hibernate.type.xml_format_mapper.legacy_format=true immediately after upgrading if you have pre-upgrade XML data, then migrate at leisure.","Pin the XML format: test stored-XML layout in golden-file tests so format changes surface in CI.","Migrate column data in the same release that changes the attribute type.","Validate external XML against the XmlMapper before it enters the column."],"tags":["hibernate","xml","jackson","sqlxml","orm","deserialization"],"backgroundTag":"xml-deserialization-failed","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}