hibernate/hibernate-orm · error · UnsupportedOperationException

Unsupported JdbcType nested in JSON: {}

Error message

Unsupported JdbcType nested in JSON: {}

What it means

The same scalar branch whitelists the JDBC type codes it can render into JSON (integers, floats, booleans, char/varchar/clob strings, enums, dates/times, decimal, duration, uuid, binary). Any other JdbcType falls through to UnsupportedOperationException naming the type — Hibernate cannot serialize that nested attribute of the JSON aggregate at all.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/type/format/StringJsonDocumentWriter.java:376

				appender.append( StringJsonDocumentMarker.QUOTE.getMarkerCharacter() );
				break;
			case SqlTypes.BINARY:
			case SqlTypes.VARBINARY:
			case SqlTypes.LONGVARBINARY:
			case SqlTypes.LONG32VARBINARY:
			case SqlTypes.BLOB:
			case SqlTypes.MATERIALIZED_BLOB:
				// These types need to be serialized as JSON string, and for efficiency uses appendString directly
				appender.append( StringJsonDocumentMarker.QUOTE.getMarkerCharacter() );
				appender.write( javaType.unwrap( (T) value, byte[].class, options ) );
				appender.append( StringJsonDocumentMarker.QUOTE.getMarkerCharacter() );
				break;
			case SqlTypes.ARRAY:
			case SqlTypes.JSON_ARRAY:
				// Caller handles this. We should never end up here actually.
				throw new IllegalStateException( "unexpected JSON array type" );
			default:
				throw new UnsupportedOperationException( "Unsupported JdbcType nested in JSON: " + jdbcType );
		}
	}

	public String getJson() {
		return appender.toString();
	}

	@Override
	public String toString() {
		return appender.toString();
	}

	private static class JsonAppender extends OutputStream implements SqlAppender {

		private final static char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();

		private final StringBuilder sb;
		private boolean escape;

View on GitHub (pinned to fad1729dce)

Solutions

  1. Read the message — it names the exact jdbcType; remap that attribute to a supported representation (e.g. AttributeConverter Point→WKT String, Duration→ISO-8601 String, nested JSON→String)
  2. Move the unsupported attribute out of the JSON aggregate into its own column
  3. Register a custom FormatMapper via hibernate.type.json_format_mapper that knows how to render the type
  4. Add an integration test that round-trips the aggregate so unsupported types fail at build time, not in production

Example fix

// before
@Embeddable
public class Address {
    private org.locationtech.jts.geom.Point location; // SqlTypes.GEOMETRY -> UnsupportedOperationException
}
// after
@Embeddable
public class Address {
    @Convert(converter = PointToStringConverter.class)
    private Point location; // stored as WKT string inside the JSON
}
Defensive patterns

Strategy: fallback

Validate before calling

static final Set<Integer> SUPPORTED = Set.of(
        SqlTypes.TINYINT, SqlTypes.SMALLINT, SqlTypes.INTEGER, SqlTypes.BOOLEAN, SqlTypes.BIT,
        SqlTypes.BIGINT, SqlTypes.FLOAT, SqlTypes.REAL, SqlTypes.DOUBLE, SqlTypes.CHAR, SqlTypes.NCHAR,
        SqlTypes.VARCHAR, SqlTypes.NVARCHAR, SqlTypes.LONGVARCHAR, SqlTypes.LONGNVARCHAR,
        SqlTypes.LONG32VARCHAR, SqlTypes.LONG32NVARCHAR, SqlTypes.CLOB, SqlTypes.MATERIALIZED_CLOB,
        SqlTypes.NCLOB, SqlTypes.MATERIALIZED_NCLOB, SqlTypes.ENUM, SqlTypes.NAMED_ENUM,
        SqlTypes.DATE, SqlTypes.TIME, SqlTypes.TIME_WITH_TIMEZONE, SqlTypes.TIME_UTC, SqlTypes.TIMESTAMP,
        SqlTypes.TIMESTAMP_WITH_TIMEZONE, SqlTypes.TIMESTAMP_UTC, SqlTypes.DECIMAL, SqlTypes.NUMERIC,
        SqlTypes.DURATION, SqlTypes.UUID, SqlTypes.BINARY, SqlTypes.VARBINARY, SqlTypes.LONGVARBINARY,
        SqlTypes.LONG32VARBINARY, SqlTypes.BLOB, SqlTypes.MATERIALIZED_BLOB);

// verify each aggregate attribute's jdbcType.getDefaultSqlTypeCode() is in SUPPORTED before enabling the mapping

Try / catch

try {
    session.persist(entity);
    session.flush();
} catch (UnsupportedOperationException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Unsupported JdbcType nested in JSON")) {
        // e.getMessage() names the jdbcType: convert that attribute or exclude it from the aggregate
        throw new MappingConfigurationException(e.getMessage(), e);
    }
    throw e;
}

Prevention

When it happens

Trigger: An embeddable mapped as a JSON aggregate (@JdbcTypeCode(SqlTypes.JSON) / @AggregateMapping) containing an attribute whose JDBC type is outside the switch: geometry (SqlTypes.GEOMETRY), nested JSON (SqlTypes.JSON), SQLXML, INTERVAL, or any custom user JdbcType.

Common situations: Adding a new attribute (Point, Interval, nested JSONB) to an @Embeddable persisted as JSON; dialect-specific types; upgrading Hibernate where the supported-type list changed between versions.

Related errors


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