hibernate/hibernate-orm · error · IllegalArgumentException
Malformed JSON. Expected array but got: " + event
Error message
Malformed JSON. Expected array but got: " + event
What it means
JsonHelper.deserializeArray expects the top-level element of a JSON column bound to a plural (array/collection) attribute to be an array. If the reader yields an object, scalar or boolean instead, it throws IllegalArgumentException('Malformed JSON. Expected array but got: <event>') - valid JSON, wrong shape for the collection mapping.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/JsonHelper.java:259
String string,
WrapperOptions options) throws SQLException {
if ( string == null ) {
return null;
}
return deserializeArray( javaType, elementJdbcType, new StringJsonDocumentReader( string ), options );
}
public static <X> X deserializeArray(
JavaType<X> javaType,
JdbcType elementJdbcType,
JsonDocumentReader reader,
WrapperOptions options) throws SQLException {
final JsonDocumentItemType event;
if ( !reader.hasNext() || ( event = reader.next() ) == JsonDocumentItemType.NULL_VALUE ) {
return null;
}
if ( event != JsonDocumentItemType.ARRAY_START ) {
throw new IllegalArgumentException("Malformed JSON. Expected array but got: " + event);
}
final CustomArrayList arrayList = new CustomArrayList();
final JavaType<?> elementJavaType = ((BasicPluralJavaType<?>) javaType).getElementJavaType();
final Class<?> preferredJavaTypeClass = elementJdbcType.getPreferredJavaTypeClass( options );
final JavaType<?> jdbcJavaType;
if ( preferredJavaTypeClass == null || preferredJavaTypeClass == elementJavaType.getJavaTypeClass() ) {
jdbcJavaType = elementJavaType;
}
else {
jdbcJavaType = options.getTypeConfiguration().getJavaTypeRegistry().resolveDescriptor( preferredJavaTypeClass );
}
final JsonValueJDBCTypeAdapter adapter = JsonValueJDBCTypeAdapterFactory.getAdapter(reader,false);
while(reader.hasNext()) {
JsonDocumentItemType type = reader.next();
switch ( type ) {
case ARRAY_END:View on GitHub (pinned to fad1729dce)
Solutions
- If the data is an object, map the attribute as an @Embedded aggregate instead of a collection.
- If the mapping is correct, migrate the stored data to a JSON array (e.g., jsonb: UPDATE t SET doc = jsonb_build_array(doc)).
Example fix
// before: column holds {"a":1} but attribute is a plural JSON type
@JdbcTypeCode(SqlTypes.JSON)
List<Item> items; // load -> Malformed JSON. Expected array but got: OBJECT_START
// after: align data with mapping
UPDATE t SET doc = jsonb_build_array(doc);
// or change mapping to @Embedded Item item; Defensive patterns
Strategy: validation
Validate before calling
// Validate the top-level shape before loading a collection attribute (Jackson example)
static void assertTopLevelArray(String json) {
com.fasterxml.jackson.databind.JsonNode n;
try { n = new com.fasterxml.jackson.databind.ObjectMapper().readTree(json); }
catch (Exception e) { throw new IllegalArgumentException("Invalid JSON", e); }
if (!n.isArray()) {
throw new IllegalArgumentException("Expected a JSON array for the collection mapping, got: " + n.getNodeType());
}
} Try / catch
try {
return session.find(Product.class, id);
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Malformed JSON. Expected array")) {
// column holds an object/scalar where a collection is mapped: fix mapping or wrap data in []
} else {
throw e;
}
} Prevention
- When flipping an attribute between embeddable and List<embeddable>, migrate the column shape too
- Validate JSON column shapes in data migrations
- Keep a single writer per JSON column
When it happens
Trigger: Reading a @JdbcTypeCode(SqlTypes.JSON) List<T>/T[] attribute whose column holds an object or scalar - mapping flipped between singular aggregate and collection, or another writer stored an object in the column.
Common situations: Refactoring an attribute from embeddable aggregate to List<embeddable> (or back) without data migration; consumers writing objects into a column the application reads as an array.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Can't parse JSON array for selectable [%s] which is not of t
- Malformed JSON. Expected object but got: " + event
- Expected JSON array end, but none found.
- Can't parse JSON object for selectable [%s] which is not of
- Expected JSON object end, but none found.
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/1b083cdded063b38.
Report an issue: GitHub.