spring-projects/spring-ai · error · IllegalArgumentException

Expected List for IN/NIN but got:

Error message

Expected List for IN/NIN but got: 

What it means

extractListValue is used by convertIn/convertNotIn: it extracts the operand value and requires it to be a java.util.List so it can be converted into Bedrock Document values for the IN/NIN operator. If the value is a scalar (String, Number, etc.), it throws an IllegalArgumentException naming the value's class.

Source

Thrown at vector-stores/spring-ai-bedrock-knowledgebase-store/src/main/java/org/springframework/ai/vectorstore/bedrockknowledgebase/BedrockKnowledgeBaseFilterExpressionConverter.java:155

		if (operand instanceof Expression expr) {
			return expr;
		}
		throw new IllegalArgumentException("Expected Expression but got: " + operand.getClass());
	}

	private Object extractValue(final Filter.Operand operand) {
		if (operand instanceof Value value) {
			return value.value();
		}
		throw new IllegalArgumentException("Expected Value but got: " + operand.getClass());
	}

	private List<?> extractListValue(final Filter.Operand operand) {
		Object value = extractValue(operand);
		if (value instanceof List) {
			return (List<?>) value;
		}
		throw new IllegalArgumentException("Expected List for IN/NIN but got: " + value.getClass());
	}

	private Document toDocument(final Object value) {
		if (value instanceof String s) {
			return Document.fromString(s);
		}
		if (value instanceof Number n) {
			return Document.fromNumber(n.toString());
		}
		if (value instanceof Boolean b) {
			return Document.fromBoolean(b);
		}
		return Document.fromString(value.toString());
	}

	private enum ComparisonOp {

		EQ, NE, GT, GTE, LT, LTE

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Wrap the membership values in a List: IN(new ExpressionText("status"), List.of("a","b"))
  2. If only one value, keep List.of(value) or use a comparison (EQ-style via supported operators) instead of IN
  3. Validate the value operand before conversion: instanceof List check on the extracted value
  4. Catch IllegalArgumentException around similaritySearch and correct the filter expression

Example fix

// before
Expression e = IN(new ExpressionText("category"), "news"); // scalar, not List
// after
Expression e = IN(new ExpressionText("category"), List.of("news"));
Defensive patterns

Strategy: validation

Validate before calling

Object v = ((Value) expr.right()).value();
if (!(v instanceof List)) { throw new IllegalArgumentException("IN/NIN requires a List value, got: " + v.getClass()); }

Type guard

List<?> requireList(Filter.Operand o) { if (o instanceof Value v && v.value() instanceof List<?> l) return l; throw new IllegalArgumentException("IN/NIN value must be a List"); }

Try / catch

try { return store.similaritySearch(request); } catch (IllegalArgumentException e) { log.warn("IN/NIN needs a List: {}", e.getMessage()); throw new BadRequestException("Filter values for IN/NIN must be lists"); }

Prevention

When it happens

Trigger: Building IN(key, "singleString") or NIN(key, 42) — i.e. the right operand's value is not a List — then converting the expression via the Bedrock converter or passing it through BedrockKnowledgeBaseVectorStore.similaritySearch.

Common situations: Assuming IN accepts a single value like SQL's 'IN (x)' style queries; generic filter builders wrapping scalars instead of lists; refactoring EQ to IN without wrapping the value in List.of(...).

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11). Data as JSON: /api/errors/cb205ea340ef65c7. Report an issue: GitHub.