hibernate/hibernate-orm · error · IllegalArgumentException

Could not deserialize string to java type: {}

Error message

Could not deserialize string to java type: {}

What it means

XML counterpart of the Jackson 3 mapper, used for @JdbcTypeCode(SqlTypes.XML) attributes: fromString() binds the XML column content with an XmlMapper and wraps any JacksonException as IllegalArgumentException('Could not deserialize string to java type: <type>'). The stored XML does not bind to the mapped Java type — wrong root/element names, collection wrapping mismatch (non-legacy format expects a 'Collection' root with 'e' elements), or value type mismatch.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/type/format/jackson/Jackson3XmlFormatMapper.java:161

					);
					return javaType.wrap( collectionWrapper.value, wrapperOptions );
				}
				else if ( javaType.getJavaTypeClass().isArray() ) {
					final CollectionWrapper<?> collectionWrapper = xmlMapper.readValue(
							charSequence.toString(),
							xmlMapper.constructType( new ParameterizedTypeImpl( CollectionWrapper.class,
									new Type[] {javaType.getJavaTypeClass().getComponentType()}, null ) )
					);
					return javaType.wrap( collectionWrapper.value, wrapperOptions );
				}
			}
			return xmlMapper.readValue(
					charSequence.toString(),
					xmlMapper.constructType( javaType.getJavaType() )
			);
		}
		catch (JacksonException 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;
		}
		if ( !legacyFormat ) {
			if ( Map.class.isAssignableFrom( javaType.getJavaTypeClass() ) ) {
				final Type keyType;
				final Type elementType;
				if ( javaType.getJavaType() instanceof ParameterizedType parameterizedType ) {
					keyType = parameterizedType.getActualTypeArguments()[0];
					elementType = parameterizedType.getActualTypeArguments()[1];
				}
				else {
					keyType = Object.class;

View on GitHub (pinned to fad1729dce)

Solutions

  1. Compare the stored XML with what Hibernate writes for the same mapping (root element, 'e' items for collections)
  2. Set hibernate.type.xml_format_mapper.legacy_format=true (or false) to match how the existing data was encoded
  3. Adjust mapping annotations (@JsonRootName, @JacksonXmlProperty/@JacksonXmlElementWrapper) or transform the stored XML to the expected shape
  4. Read the cause JacksonException for the exact element/path that failed

Example fix

# before: rows written by an older Hibernate (wrapped collection format), new mapper reads them
hibernate.type.xml_format_mapper.legacy_format=false
# after: match the reader to the stored format
hibernate.type.xml_format_mapper.legacy_format=true
Defensive patterns

Strategy: try-catch

Validate before calling

// check the stored XML binds before mass-loading
static <T> void validateXmlMatches(String xml, tools.jackson.databind.JavaType type,
                                   tools.jackson.dataformat.xml.XmlMapper mapper) {
    try {
        mapper.readValue(xml, type);
    } catch (tools.jackson.core.JacksonException e) {
        throw new IllegalArgumentException("XML column incompatible: " + e.getMessage(), e);
    }
}

Try / catch

try {
    MyEntity e = session.find(MyEntity.class, id);
} catch (IllegalArgumentException ex) {
    if (ex.getMessage() != null && ex.getMessage().startsWith("Could not deserialize string to java type")) {
        Throwable cause = ex.getCause(); // JacksonException naming element/path
        throw new DataQualityException("XML column incompatible with mapping: " + cause.getMessage(), ex);
    }
    throw ex;
}

Prevention

When it happens

Trigger: Loading an @JdbcTypeCode(SqlTypes.XML) entity when: the root element name does not match the mapping; collections are stored in the other encoding style (the mapper was built with the hibernate.type.xml_format_mapper.legacy_format flag mismatching the data); the XML comes from an external producer with different element names; a field type changed (single element vs List).

Common situations: Migrating Hibernate versions where the default XML collection encoding changed (legacy wrapped vs unwrapped format); consuming external XML not generated by Hibernate; changing the mapped Java type without transforming existing rows.

Related errors


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