{"record":{"id":"3d874b8c716e562c","repo":"hibernate/hibernate-orm","slug":"unsupported-jdbctype-nested-in-json-3d874b","errorCode":null,"errorMessage":"Unsupported JdbcType nested in JSON: {}","messagePattern":"Unsupported JdbcType nested in JSON: (.+?)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/type/format/StringJsonDocumentWriter.java","lineNumber":376,"sourceCode":"\t\t\t\tappender.append( StringJsonDocumentMarker.QUOTE.getMarkerCharacter() );\n\t\t\t\tbreak;\n\t\t\tcase SqlTypes.BINARY:\n\t\t\tcase SqlTypes.VARBINARY:\n\t\t\tcase SqlTypes.LONGVARBINARY:\n\t\t\tcase SqlTypes.LONG32VARBINARY:\n\t\t\tcase SqlTypes.BLOB:\n\t\t\tcase SqlTypes.MATERIALIZED_BLOB:\n\t\t\t\t// These types need to be serialized as JSON string, and for efficiency uses appendString directly\n\t\t\t\tappender.append( StringJsonDocumentMarker.QUOTE.getMarkerCharacter() );\n\t\t\t\tappender.write( javaType.unwrap( (T) value, byte[].class, options ) );\n\t\t\t\tappender.append( StringJsonDocumentMarker.QUOTE.getMarkerCharacter() );\n\t\t\t\tbreak;\n\t\t\tcase SqlTypes.ARRAY:\n\t\t\tcase SqlTypes.JSON_ARRAY:\n\t\t\t\t// Caller handles this. We should never end up here actually.\n\t\t\t\tthrow new IllegalStateException( \"unexpected JSON array type\" );\n\t\t\tdefault:\n\t\t\t\tthrow new UnsupportedOperationException( \"Unsupported JdbcType nested in JSON: \" + jdbcType );\n\t\t}\n\t}\n\n\tpublic String getJson() {\n\t\treturn appender.toString();\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn appender.toString();\n\t}\n\n\tprivate static class JsonAppender extends OutputStream implements SqlAppender {\n\n\t\tprivate final static char[] HEX_ARRAY = \"0123456789ABCDEF\".toCharArray();\n\n\t\tprivate final StringBuilder sb;\n\t\tprivate boolean escape;","sourceCodeStart":358,"sourceCodeEnd":394,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/type/format/StringJsonDocumentWriter.java#L358-L394","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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)","Move the unsupported attribute out of the JSON aggregate into its own column","Register a custom FormatMapper via hibernate.type.json_format_mapper that knows how to render the type","Add an integration test that round-trips the aggregate so unsupported types fail at build time, not in production"],"exampleFix":"// before\n@Embeddable\npublic class Address {\n    private org.locationtech.jts.geom.Point location; // SqlTypes.GEOMETRY -> UnsupportedOperationException\n}\n// after\n@Embeddable\npublic class Address {\n    @Convert(converter = PointToStringConverter.class)\n    private Point location; // stored as WKT string inside the JSON\n}","handlingStrategy":"fallback","validationCode":"static final Set<Integer> SUPPORTED = Set.of(\n        SqlTypes.TINYINT, SqlTypes.SMALLINT, SqlTypes.INTEGER, SqlTypes.BOOLEAN, SqlTypes.BIT,\n        SqlTypes.BIGINT, SqlTypes.FLOAT, SqlTypes.REAL, SqlTypes.DOUBLE, SqlTypes.CHAR, SqlTypes.NCHAR,\n        SqlTypes.VARCHAR, SqlTypes.NVARCHAR, SqlTypes.LONGVARCHAR, SqlTypes.LONGNVARCHAR,\n        SqlTypes.LONG32VARCHAR, SqlTypes.LONG32NVARCHAR, SqlTypes.CLOB, SqlTypes.MATERIALIZED_CLOB,\n        SqlTypes.NCLOB, SqlTypes.MATERIALIZED_NCLOB, SqlTypes.ENUM, SqlTypes.NAMED_ENUM,\n        SqlTypes.DATE, SqlTypes.TIME, SqlTypes.TIME_WITH_TIMEZONE, SqlTypes.TIME_UTC, SqlTypes.TIMESTAMP,\n        SqlTypes.TIMESTAMP_WITH_TIMEZONE, SqlTypes.TIMESTAMP_UTC, SqlTypes.DECIMAL, SqlTypes.NUMERIC,\n        SqlTypes.DURATION, SqlTypes.UUID, SqlTypes.BINARY, SqlTypes.VARBINARY, SqlTypes.LONGVARBINARY,\n        SqlTypes.LONG32VARBINARY, SqlTypes.BLOB, SqlTypes.MATERIALIZED_BLOB);\n\n// verify each aggregate attribute's jdbcType.getDefaultSqlTypeCode() is in SUPPORTED before enabling the mapping","typeGuard":null,"tryCatchPattern":"try {\n    session.persist(entity);\n    session.flush();\n} catch (UnsupportedOperationException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Unsupported JdbcType nested in JSON\")) {\n        // e.getMessage() names the jdbcType: convert that attribute or exclude it from the aggregate\n        throw new MappingConfigurationException(e.getMessage(), e);\n    }\n    throw e;\n}","preventionTips":["Keep exotic types (geometry, interval, nested JSON) out of JSON aggregates or convert them to String via AttributeConverter","Add a startup or test-time check listing the JDBC type codes of every aggregate attribute","Provide a custom FormatMapper (hibernate.type.json_format_mapper) for types Hibernate cannot render natively"],"tags":["hibernate","json","serialization","aggregate-mapping","unsupported-type"],"backgroundTag":"unsupported-type-mapping","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}