hibernate/hibernate-orm · error · IllegalStateException

unexpected JSON array type

Error message

unexpected JSON array type

What it means

convertedBasicValueToString() serializes one nested attribute of a JSON aggregate and explicitly refuses JDBC types whose default SQL type code is SqlTypes.ARRAY or JSON_ARRAY — the comment states the caller must emit arrays via startArray()/values/endArray() instead. Reaching this throw means Hibernate's own serialization path routed an array-typed value into the scalar branch: an internal invariant break, not a user input error.

Source

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

				appender.append( StringJsonDocumentMarker.QUOTE.getMarkerCharacter() );
				javaType.appendEncodedString( appender, (T) value );
				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();

View on GitHub (pinned to fad1729dce)

Solutions

  1. Remap the nested collection so Hibernate serializes it as JSON content (remove @JdbcTypeCode(SqlTypes.ARRAY)/JSON_ARRAY from the attribute)
  2. Test against the latest 7.x patch release and search the HHH JIRA for 'unexpected JSON array type' — JSON aggregate handling has active fixes
  3. Plug in a custom FormatMapper via hibernate.type.json_format_mapper that serializes the aggregate end-to-end
  4. If reproducible on the latest release, report to Hibernate JIRA with the entity mapping and dialect

Example fix

// before
@Embeddable
public class Details {
    @JdbcTypeCode(SqlTypes.ARRAY)   // routed into scalar branch -> IllegalStateException
    private List<String> tags;
}
// after
@Embeddable
public class Details {
    // let Hibernate map the collection inside the JSON document
    private List<String> tags;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// fail fast at startup: no aggregate attribute may use an array JdbcType
static void checkAggregateAttributes(org.hibernate.metamodel.MappingMetamodel metamodel) {
    metamodel.getEmbeddables().forEach(embeddable -> embeddable.getAttributes().forEach(attr -> {
        // reject attributes resolved to SqlTypes.ARRAY / SqlTypes.JSON_ARRAY inside JSON aggregates
    }));
}

Try / catch

try {
    session.merge(entity);
    session.flush();
} catch (IllegalStateException e) {
    if ("unexpected JSON array type".equals(e.getMessage())) {
        // Hibernate internal invariant: remap the nested collection attribute and retry
        throw new MappingConfigurationException("Nested array attribute inside JSON aggregate is not supported - map it as JSON", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: An embeddable/aggregate mapped to JSON containing an attribute annotated @JdbcTypeCode(SqlTypes.ARRAY) or SqlTypes.JSON_ARRAY (List or primitive array) where the dialect's writer passes it into serializeJsonValue() instead of the array callbacks; typically on dialects with native JSON aggregate support (Oracle, DB2, SQL Server).

Common situations: Mapping a List<T>/T[] field inside a JSON aggregate with an array JdbcType; upgrading Hibernate across versions where JSON aggregate serialization was reworked; a custom JdbcType whose getDefaultSqlTypeCode() reports ARRAY.

Related errors


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