{"record":{"id":"1b083cdded063b38","repo":"hibernate/hibernate-orm","slug":"malformed-json-expected-array-but-got-event","errorCode":null,"errorMessage":"Malformed JSON. Expected array but got: \" + event","messagePattern":"Malformed JSON\\. Expected array but got: \" \\+ event","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/JsonHelper.java","lineNumber":259,"sourceCode":"\t\t\tString string,\n\t\t\tWrapperOptions options) throws SQLException {\n\t\tif ( string == null ) {\n\t\t\treturn null;\n\t\t}\n\t\treturn deserializeArray( javaType, elementJdbcType, new StringJsonDocumentReader( string ), options );\n\t}\n\n\tpublic static <X> X deserializeArray(\n\t\t\tJavaType<X> javaType,\n\t\t\tJdbcType elementJdbcType,\n\t\t\tJsonDocumentReader reader,\n\t\t\tWrapperOptions options) throws SQLException {\n\t\tfinal JsonDocumentItemType event;\n\t\tif ( !reader.hasNext() || ( event = reader.next() ) == JsonDocumentItemType.NULL_VALUE ) {\n\t\t\treturn null;\n\t\t}\n\t\tif ( event != JsonDocumentItemType.ARRAY_START ) {\n\t\t\tthrow new IllegalArgumentException(\"Malformed JSON. Expected array but got: \" + event);\n\t\t}\n\n\t\tfinal CustomArrayList arrayList = new CustomArrayList();\n\t\tfinal JavaType<?> elementJavaType = ((BasicPluralJavaType<?>) javaType).getElementJavaType();\n\t\tfinal Class<?> preferredJavaTypeClass = elementJdbcType.getPreferredJavaTypeClass( options );\n\t\tfinal JavaType<?> jdbcJavaType;\n\t\tif ( preferredJavaTypeClass == null || preferredJavaTypeClass == elementJavaType.getJavaTypeClass() ) {\n\t\t\tjdbcJavaType = elementJavaType;\n\t\t}\n\t\telse {\n\t\t\tjdbcJavaType = options.getTypeConfiguration().getJavaTypeRegistry().resolveDescriptor( preferredJavaTypeClass );\n\t\t}\n\n\t\tfinal JsonValueJDBCTypeAdapter adapter = JsonValueJDBCTypeAdapterFactory.getAdapter(reader,false);\n\t\twhile(reader.hasNext()) {\n\t\t\tJsonDocumentItemType type = reader.next();\n\t\t\tswitch ( type ) {\n\t\t\t\tcase ARRAY_END:","sourceCodeStart":241,"sourceCodeEnd":277,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/JsonHelper.java#L241-L277","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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))."],"exampleFix":"// before: column holds {\"a\":1} but attribute is a plural JSON type\n@JdbcTypeCode(SqlTypes.JSON)\nList<Item> items; // load -> Malformed JSON. Expected array but got: OBJECT_START\n\n// after: align data with mapping\nUPDATE t SET doc = jsonb_build_array(doc);\n// or change mapping to @Embedded Item item;","handlingStrategy":"validation","validationCode":"// Validate the top-level shape before loading a collection attribute (Jackson example)\nstatic void assertTopLevelArray(String json) {\n    com.fasterxml.jackson.databind.JsonNode n;\n    try { n = new com.fasterxml.jackson.databind.ObjectMapper().readTree(json); }\n    catch (Exception e) { throw new IllegalArgumentException(\"Invalid JSON\", e); }\n    if (!n.isArray()) {\n        throw new IllegalArgumentException(\"Expected a JSON array for the collection mapping, got: \" + n.getNodeType());\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    return session.find(Product.class, id);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Malformed JSON. Expected array\")) {\n        // column holds an object/scalar where a collection is mapped: fix mapping or wrap data in []\n    } else {\n        throw e;\n    }\n}","preventionTips":["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"],"tags":["hibernate","json","malformed-data","collection-mapping","type-mismatch"],"backgroundTag":"malformed-json-data","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}