{"record":{"id":"7330b6b6dabb90f0","repo":"hibernate/hibernate-orm","slug":"could-not-deserialize-string-to-java-type-7330b6","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/jaxb/JaxbXmlFormatMapper.java","lineNumber":272,"sourceCode":"\t\t\t\t\t//noinspection unchecked\n\t\t\t\t\tfinal T array = (T) Array.newInstance( valueClass, length );\n\t\t\t\t\tint i = 0;\n\t\t\t\t\tfor ( Object element : elements ) {\n\t\t\t\t\t\tfinal Object value = valueTransformer.fromJAXBElement( element, unmarshaller );\n\t\t\t\t\t\tArray.set( array, i, value );\n\t\t\t\t\t\ti++;\n\t\t\t\t\t}\n\t\t\t\t\treturn array;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfinal JAXBContext context = JAXBContext.newInstance( javaType.getJavaTypeClass() );\n\t\t\t\t//noinspection unchecked\n\t\t\t\treturn (T) context.createUnmarshaller().unmarshal( new StringReader( charSequence.toString() ) );\n\t\t\t}\n\t\t}\n\t\tcatch (JAXBException 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\ttry {\n\t\t\tfinal StringWriter stringWriter = new StringWriter();\n\t\t\tfinal StringBuilderSqlAppender appender = new StringBuilderSqlAppender();\n\t\t\tif ( Map.class.isAssignableFrom( javaType.getJavaTypeClass() ) ) {\n\t\t\t\tfinal JAXBContext context;\n\t\t\t\tfinal Class<?> keyClass;\n\t\t\t\tfinal Class<?> valueClass;\n\t\t\t\tfinal Map<?, ?> map = (Map<?, ?>) value;\n\t\t\t\tif ( javaType.getJavaType() instanceof ParameterizedType parameterizedType ) {\n\t\t\t\t\tfinal Type[] typeArguments = parameterizedType.getActualTypeArguments();","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/type/format/jaxb/JaxbXmlFormatMapper.java#L254-L290","documentation":"JaxbXmlFormatMapper is the FormatMapper Hibernate uses for @JdbcTypeCode(SqlTypes.SQLXML) attributes when a jakarta.xml.bind (JAXB) runtime is present (see the JAXBContext usage at JaxbXmlFormatMapper.java:266-282). This IllegalArgumentException wraps a JAXBException thrown while unmarshalling the stored column XML into the attribute type. The wrapped JAXBException (UnmarshalException, validation error) carries the actual reason.","triggerScenarios":"Loading an entity whose XML attribute class is not JAXB-mappable (no public no-arg constructor, fields without @XmlElement mapping, java.time fields without an XmlAdapter); stored XML whose element structure does not match the annotated class; malformed XML in the column.","commonSituations":"Annotating a type with @JdbcTypeCode(SqlTypes.SQLXML) assuming Jackson-style behavior while the classpath resolves the JAXB mapper; keeping Jackson annotations on a class now serialized by JAXB; schema drift between stored XML and the annotated class after refactors; missing jakarta.xml.bind annotations entirely.","solutions":["Annotate the attribute type for JAXB: @XmlRootElement, @XmlAccessorType(XmlAccessType.FIELD), @XmlElement names matching the stored XML.","Add a public no-arg constructor and register @XmlJavaTypeAdapters for java.time and other non-JAXB types.","Fix or migrate stored XML rows whose structure does not match the class.","If the type is Jackson-oriented, force the Jackson XML mapper instead (hibernate.type.xml_format_mapper=jackson-xml) so your Jackson annotations apply."],"exampleFix":"// before - no JAXB annotations, unmarshalling fails\npublic class Config {\n    public String key;   // JAXB maps nothing, stored XML mismatches\n}\n\n// after - JAXB-mapped type\n@XmlRootElement(name = \"config\")\n@XmlAccessorType(XmlAccessType.FIELD)\npublic class Config {\n    @XmlElement(name = \"key\")\n    public String key;\n}","handlingStrategy":"try-catch","validationCode":"// Validate stored XML against the JAXB context before it becomes an entity\nstatic void assertUnmarshallable(String xml, Class<?> type) {\n    try {\n        JAXBContext.newInstance( type ).createUnmarshaller().unmarshal( new StringReader( xml ) );\n    } catch ( JAXBException e ) {\n        throw new IllegalArgumentException( \"Stored XML will fail on load: \" + e.getMessage(), e );\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    return session.find( Doc.class, id );\n} catch ( IllegalArgumentException e ) {\n    if ( e.getCause() instanceof jakarta.xml.bind.JAXBException jaxb ) {\n        // stored XML <-> annotated class mismatch; check the linked cause\n    } else throw e;\n}","preventionTips":["Annotate SQLXML types with @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) from day one.","Provide @XmlJavaTypeAdapter for java.time and other non-JAXB types.","Decide the mapper deliberately (hibernate.type.xml_format_mapper) so annotations and implementation match."],"tags":["hibernate","xml","jaxb","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"}