hibernate/hibernate-orm · error · IllegalArgumentException

Could not deserialize string to java type: {}

Error message

Could not deserialize string to java type: {}

What it means

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.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/type/format/jaxb/JaxbXmlFormatMapper.java:272

					//noinspection unchecked
					final T array = (T) Array.newInstance( valueClass, length );
					int i = 0;
					for ( Object element : elements ) {
						final Object value = valueTransformer.fromJAXBElement( element, unmarshaller );
						Array.set( array, i, value );
						i++;
					}
					return array;
				}
			}
			else {
				final JAXBContext context = JAXBContext.newInstance( javaType.getJavaTypeClass() );
				//noinspection unchecked
				return (T) context.createUnmarshaller().unmarshal( new StringReader( charSequence.toString() ) );
			}
		}
		catch (JAXBException e) {
			throw new IllegalArgumentException( "Could not deserialize string to java type: " + javaType, e );
		}
	}

	@Override
	public <T> String toString(T value, JavaType<T> javaType, WrapperOptions wrapperOptions) {
		if ( javaType.getJavaType() == String.class || javaType.getJavaType() == Object.class ) {
			return (String) value;
		}
		try {
			final StringWriter stringWriter = new StringWriter();
			final StringBuilderSqlAppender appender = new StringBuilderSqlAppender();
			if ( Map.class.isAssignableFrom( javaType.getJavaTypeClass() ) ) {
				final JAXBContext context;
				final Class<?> keyClass;
				final Class<?> valueClass;
				final Map<?, ?> map = (Map<?, ?>) value;
				if ( javaType.getJavaType() instanceof ParameterizedType parameterizedType ) {
					final Type[] typeArguments = parameterizedType.getActualTypeArguments();

View on GitHub (pinned to fad1729dce)

Solutions

  1. Annotate the attribute type for JAXB: @XmlRootElement, @XmlAccessorType(XmlAccessType.FIELD), @XmlElement names matching the stored XML.
  2. Add a public no-arg constructor and register @XmlJavaTypeAdapters for java.time and other non-JAXB types.
  3. Fix or migrate stored XML rows whose structure does not match the class.
  4. If the type is Jackson-oriented, force the Jackson XML mapper instead (hibernate.type.xml_format_mapper=jackson-xml) so your Jackson annotations apply.

Example fix

// before - no JAXB annotations, unmarshalling fails
public class Config {
    public String key;   // JAXB maps nothing, stored XML mismatches
}

// after - JAXB-mapped type
@XmlRootElement(name = "config")
@XmlAccessorType(XmlAccessType.FIELD)
public class Config {
    @XmlElement(name = "key")
    public String key;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate stored XML against the JAXB context before it becomes an entity
static void assertUnmarshallable(String xml, Class<?> type) {
    try {
        JAXBContext.newInstance( type ).createUnmarshaller().unmarshal( new StringReader( xml ) );
    } catch ( JAXBException e ) {
        throw new IllegalArgumentException( "Stored XML will fail on load: " + e.getMessage(), e );
    }
}

Try / catch

try {
    return session.find( Doc.class, id );
} catch ( IllegalArgumentException e ) {
    if ( e.getCause() instanceof jakarta.xml.bind.JAXBException jaxb ) {
        // stored XML <-> annotated class mismatch; check the linked cause
    } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/7330b6b6dabb90f0. Report an issue: GitHub.