{"record":{"id":"27d8437db9cc89e6","repo":"spring-projects/spring-ai","slug":"expected-a-value-operand-but-got-27d843","errorCode":null,"errorMessage":"Expected a Value operand but got: ","messagePattern":"Expected a Value operand but got: ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"vector-stores/spring-ai-s3-vector-store/src/main/java/org/springframework/ai/vectorstore/s3/S3VectorStoreFilterExpressionEvaluator.java","lineNumber":116,"sourceCode":"\n\tprivate @Nullable Object metadataValue(Filter.Operand operand, Map<String, Object> metadata) {\n\t\tif (operand instanceof Filter.Key key) {\n\t\t\tString k = key.key();\n\t\t\tif (k.length() >= 2\n\t\t\t\t\t&& ((k.startsWith(\"\\\"\") && k.endsWith(\"\\\"\")) || (k.startsWith(\"'\") && k.endsWith(\"'\")))) {\n\t\t\t\tk = k.substring(1, k.length() - 1);\n\t\t\t}\n\t\t\treturn metadata.get(k);\n\t\t}\n\t\tthrow new IllegalArgumentException(\"Expected a Key operand but got: \" + operand.getClass().getName());\n\t}\n\n\tprivate Object filterValue(Filter.Operand operand) {\n\t\tif (operand instanceof Filter.Value filterValue) {\n\t\t\tObject value = filterValue.value();\n\t\t\treturn (value instanceof Date date) ? DATE_FORMATTER.format(date.toInstant()) : value;\n\t\t}\n\t\tthrow new IllegalArgumentException(\"Expected a Value operand but got: \" + operand.getClass().getName());\n\t}\n\n\tprivate int compare(@Nullable Object metaVal, @Nullable Object filterVal) {\n\t\tif (metaVal == null && filterVal == null) {\n\t\t\treturn 0;\n\t\t}\n\t\tif (metaVal == null) {\n\t\t\treturn -1;\n\t\t}\n\t\tif (filterVal == null) {\n\t\t\treturn 1;\n\t\t}\n\t\tif (metaVal instanceof Number n1 && filterVal instanceof Number n2) {\n\t\t\treturn Double.compare(n1.doubleValue(), n2.doubleValue());\n\t\t}\n\t\tif (Objects.equals(metaVal, filterVal)) {\n\t\t\treturn 0;\n\t\t}","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/vector-stores/spring-ai-s3-vector-store/src/main/java/org/springframework/ai/vectorstore/s3/S3VectorStoreFilterExpressionEvaluator.java#L98-L134","documentation":"filterValue resolves the right side of a comparison and requires a Filter.Value operand holding the literal. A Filter.Key, Group, or nested Expression in the right-hand position throws IllegalArgumentException naming the actual operand class — the evaluator does not support field-to-field comparisons.","triggerScenarios":"Building a comparison whose right operand is another metadata key (field == field), or accidentally wrapping the literal in a Key instead of Value, then running S3VectorStore similaritySearch post-filtering.","commonSituations":"Attempts at field-to-field filters (e.g. createdAt == updatedAt) unsupported by S3 Vectors post-filter evaluation; constructor argument mix-ups; ports from stores that support key-on-right comparisons.","solutions":["Use a literal Filter.Value on the right side; compute the comparison value in Java before filtering.","For field-to-field logic, filter results client-side after similaritySearch instead of expressing it in the filter.","Check operand construction: literals must be wrapped with new Filter.Value(x), field names with new Filter.Key(\"x\").","Use Filter.expr(...) to parse the filter string and get correct operand wrapping automatically."],"exampleFix":"// before\nnew Filter.Expression(Filter.ExpressionType.EQ, new Filter.Key(\"status\"), new Filter.Key(\"active\"))\n// after\nnew Filter.Expression(Filter.ExpressionType.EQ, new Filter.Key(\"status\"), new Filter.Value(\"active\"))","handlingStrategy":"validation","validationCode":"static void requireValueRight(Filter.Expression e) {\n  if (List.of(EQ, NE, GT, GTE, LT, LTE, IN, NIN).contains(e.type())\n      && !(e.right() instanceof Filter.Value)) throw new IllegalStateException(\"Right side must be a literal Value\");\n}","typeGuard":"static boolean isValueRight(Filter.Expression e) { return e.right() instanceof Filter.Value; }","tryCatchPattern":"try { store.similaritySearch(req); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith(\"Expected a Value operand\")) { /* replace key-on-right with a computed literal */ } }","preventionTips":["Wrap literals in Filter.Value, field names in Filter.Key — check argument order at call sites.","Field-to-field comparisons are unsupported; compute values in Java first.","Use the string DSL (Filter.expr) to avoid operand wrapping mistakes."],"tags":["vector-store","filter-expression","operand-order","post-filtering","aws-s3-vectors"],"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-14T11:17:12.474Z"}