{"record":{"id":"cb205ea340ef65c7","repo":"spring-projects/spring-ai","slug":"expected-list-for-in-nin-but-got","errorCode":null,"errorMessage":"Expected List for IN/NIN but got: ","messagePattern":"Expected List for IN/NIN but got: ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"vector-stores/spring-ai-bedrock-knowledgebase-store/src/main/java/org/springframework/ai/vectorstore/bedrockknowledgebase/BedrockKnowledgeBaseFilterExpressionConverter.java","lineNumber":155,"sourceCode":"\t\tif (operand instanceof Expression expr) {\n\t\t\treturn expr;\n\t\t}\n\t\tthrow new IllegalArgumentException(\"Expected Expression but got: \" + operand.getClass());\n\t}\n\n\tprivate Object extractValue(final Filter.Operand operand) {\n\t\tif (operand instanceof Value value) {\n\t\t\treturn value.value();\n\t\t}\n\t\tthrow new IllegalArgumentException(\"Expected Value but got: \" + operand.getClass());\n\t}\n\n\tprivate List<?> extractListValue(final Filter.Operand operand) {\n\t\tObject value = extractValue(operand);\n\t\tif (value instanceof List) {\n\t\t\treturn (List<?>) value;\n\t\t}\n\t\tthrow new IllegalArgumentException(\"Expected List for IN/NIN but got: \" + value.getClass());\n\t}\n\n\tprivate Document toDocument(final Object value) {\n\t\tif (value instanceof String s) {\n\t\t\treturn Document.fromString(s);\n\t\t}\n\t\tif (value instanceof Number n) {\n\t\t\treturn Document.fromNumber(n.toString());\n\t\t}\n\t\tif (value instanceof Boolean b) {\n\t\t\treturn Document.fromBoolean(b);\n\t\t}\n\t\treturn Document.fromString(value.toString());\n\t}\n\n\tprivate enum ComparisonOp {\n\n\t\tEQ, NE, GT, GTE, LT, LTE","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/vector-stores/spring-ai-bedrock-knowledgebase-store/src/main/java/org/springframework/ai/vectorstore/bedrockknowledgebase/BedrockKnowledgeBaseFilterExpressionConverter.java#L137-L173","documentation":"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.","triggerScenarios":"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.","commonSituations":"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(...).","solutions":["Wrap the membership values in a List: IN(new ExpressionText(\"status\"), List.of(\"a\",\"b\"))","If only one value, keep List.of(value) or use a comparison (EQ-style via supported operators) instead of IN","Validate the value operand before conversion: instanceof List check on the extracted value","Catch IllegalArgumentException around similaritySearch and correct the filter expression"],"exampleFix":"// before\nExpression e = IN(new ExpressionText(\"category\"), \"news\"); // scalar, not List\n// after\nExpression e = IN(new ExpressionText(\"category\"), List.of(\"news\"));","handlingStrategy":"validation","validationCode":"Object v = ((Value) expr.right()).value();\nif (!(v instanceof List)) { throw new IllegalArgumentException(\"IN/NIN requires a List value, got: \" + v.getClass()); }","typeGuard":"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\"); }","tryCatchPattern":"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\"); }","preventionTips":["Always pass List.of(...) to IN/NIN, even for single values","Wrap scalars when converting EQ to IN","Validate membership values are Lists during filter construction","Test IN and NIN filters explicitly"],"tags":["bedrock","filter-expression","in-operator","aws"],"backgroundTag":"invalid-argument-value","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}