hibernate/hibernate-orm · error · IllegalArgumentException

Can't parse JSON array for selectable [%s] which is not of t

Error message

Can't parse JSON array for selectable [%s] which is not of type BasicPluralType.

What it means

While parsing a JSON document into an embeddable, encountering ARRAY_START for a selectable whose JdbcMapping is not a BasicPluralType throws IllegalArgumentException - the stored JSON holds an array where the mapping expects a scalar or embeddable. Example: the attribute is Integer but the column value is [1,2].

Source

Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/JsonHelper.java:104

					final int selectableIndex = currentEmbeddableMappingType.getSelectableIndex( selectableName );
					if ( selectableIndex < 0 ) {
						throw new IllegalArgumentException(
								String.format(
										"Could not find selectable [%s] in embeddable type [%s] for JSON processing.",
										selectableName,
										currentEmbeddableMappingType.getMappedJavaType().getJavaTypeClass().getName()
								)
						);
					}
					final SelectableMapping selectableMapping =
							currentEmbeddableMappingType.getJdbcValueSelectable( selectableIndex );
					currentSelectableData = new SelectableData( selectableName, selectableIndex, selectableMapping );
				}
				case ARRAY_START -> {
					assert currentSelectableData != null;

					if ( !(currentSelectableData.selectableMapping.getJdbcMapping() instanceof BasicPluralType<?, ?> pluralType) ) {
						throw new IllegalArgumentException(
								String.format(
										"Can't parse JSON array for selectable [%s] which is not of type BasicPluralType.",
										ParseLevel.determineSelectablePath( parseLevel, currentSelectableData )
								)
						);
					}
					parseLevel.push( new ParseLevel( currentSelectableData, pluralType ) );
					currentSelectableData = null;
				}
				case ARRAY_END -> {
					assert currentLevel.arrayType != null;
					assert currentLevel.selectableData != null;

					parseLevel.pop();
					final ParseLevel parentLevel = parseLevel.getCurrent();

					assert parentLevel.embeddableMappingType != null;
					// flush array values

View on GitHub (pinned to fad1729dce)

Solutions

  1. If the attribute really is a collection, map it as one: List<T>/T[] with @JdbcTypeCode(SqlTypes.JSON) (a BasicPluralType) so ARRAY_START is legal.
  2. If the attribute is scalar, fix the stored data to a scalar value instead of an array.

Example fix

// before: data is {"tags":["a","b"]} but attribute is scalar
@Embeddable public class Meta { String tags; }
// load -> Can't parse JSON array for selectable [tags]

// after: map it as the collection it is
@Embeddable public class Meta {
    @JdbcTypeCode(SqlTypes.JSON)
    List<String> tags;
}
// or fix the data: UPDATE t SET doc = '{"tags":"a,b"}';
Defensive patterns

Strategy: validation

Validate before calling

// Before relying on a load, check scalar keys do not hold arrays (Jackson example)
static void assertNoArraysOnScalarKeys(JsonNode doc, Set<String> scalarKeys) {
    for (String key : scalarKeys) {
        JsonNode n = doc.get(key);
        if (n != null && n.isArray()) {
            throw new IllegalStateException("Key '" + key + "' holds an array but is mapped as scalar");
        }
    }
}

Try / catch

try {
    return session.find(Product.class, id);
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().contains("not of type BasicPluralType")) {
        // stored array vs scalar mapping: fix the attribute to a plural JSON type or migrate the data
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Loading an aggregate/json-mapped embeddable whose stored document contains an array under a key mapped to a non-collection attribute; data written by an older mapping where the attribute was a List and later changed to a scalar without data migration (or vice versa).

Common situations: Changing an embeddable attribute between List<T> and T without migrating the JSON column; other applications writing arrays into the column; copy-pasted fixture data.

Related errors


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