{"record":{"id":"58152752a40b6ee1","repo":"hibernate/hibernate-orm","slug":"expected-array-or-collection-value-but-got","errorCode":null,"errorMessage":"Expected array or collection value, but got: ","messagePattern":"Expected array or collection value, but got: ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/spi/JsonGeneratingVisitor.java","lineNumber":97,"sourceCode":"\t\t\t\t\tvisit( embeddableMappingType, Array.get( values, j ), options, writer );\n\t\t\t\t}\n\t\t\t\tcatch (IOException e) {\n\t\t\t\t\tthrow new IllegalArgumentException( \"Could not serialize array element\", e );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if ( values instanceof Collection<?> collection ) {\n\t\t\tfor ( final var item : collection ) {\n\t\t\t\ttry {\n\t\t\t\t\tvisit( embeddableMappingType, item, options, writer );\n\t\t\t\t}\n\t\t\t\tcatch (IOException e) {\n\t\t\t\t\tthrow new IllegalArgumentException( \"Could not serialize array element\", e );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"Expected array or collection value, but got: \" + values.getClass().getName()\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate void visitBasicPluralValues(\n\t\t\tJavaType<?> elementJavaType,\n\t\t\tJdbcType elementJdbcType,\n\t\t\tObject values,\n\t\t\tWrapperOptions options,\n\t\t\tJsonDocumentWriter writer) {\n\t\tif ( values.getClass().isArray() ) {\n\t\t\tfinal var length = Array.getLength( values );\n\t\t\tfor ( int j = 0; j < length; j++ ) {\n\t\t\t\tfinal var item = Array.get( values, j );\n\t\t\t\tif ( item == null ) {\n\t\t\t\t\twriter.nullValue();\n\t\t\t\t}","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/spi/JsonGeneratingVisitor.java#L79-L115","documentation":"JsonGeneratingVisitor.visitArray accepts only Java arrays and java.util.Collection values when serializing an aggregate array element. If the runtime value is neither - a singular object, a wrapper, or an Iterator - it throws IllegalArgumentException naming the actual class.","triggerScenarios":"The JavaType of an array-typed aggregate element hands a non-plural value to the serializer: a custom BasicPluralJavaType or JavaType whose wrap/unwrap returns a scalar, an AttributeConverter that strips the collection, or an element mapping whose declared type does not match the stored value type.","commonSituations":"Custom plural JavaTypes for array columns; converters applied to aggregate array attributes; mapping an attribute as an array aggregate while the domain property is singular.","solutions":["Make the custom JavaType/converter return an actual array or Collection for aggregate array values.","Fix the attribute mapping so the declared element type matches the runtime value type.","If the property is genuinely singular, map it as a plain aggregate (not an array aggregate)."],"exampleFix":"// before: custom plural JavaType returns a scalar\npublic Object wrap(Object value, WrapperOptions o) {\n    return ((Ids) value).first();      // -> Expected array or collection value\n}\n// after: return the plural form\npublic Object wrap(Object value, WrapperOptions o) {\n    return ((Ids) value).toList();     // List/Array is accepted\n}","handlingStrategy":"type-guard","validationCode":"static boolean isPluralValue(Object value) {\n    return value == null || value instanceof Collection<?> || value.getClass().isArray();\n}","typeGuard":"static boolean canBindAsAggregateArray(Object value) {\n    return value == null || value instanceof Object[]\n        || value instanceof Collection<?> || value.getClass().isArray();\n}","tryCatchPattern":"try {\n    session.persist(order);\n} catch (IllegalArgumentException ex) {\n    if (ex.getMessage() != null && ex.getMessage().startsWith(\"Expected array or collection value\")) {\n        throw new IllegalStateException(\n            \"Aggregate array attribute holds a non-plural value; fix the JavaType/converter\", ex);\n    }\n    throw ex;\n}","preventionTips":["Make custom plural JavaTypes and converters always return arrays or Collections for aggregate array values.","Assert the runtime value type matches the declared aggregate element type in unit tests.","Do not map singular properties through array aggregate types."],"tags":["hibernate","json","json-aggregate","array-mapping","custom-javatype"],"backgroundTag":"value-type-mismatch","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}