{"record":{"id":"65da6d557fbb54c2","repo":"spring-projects/spring-ai","slug":"tag-operand-0-not-supported","errorCode":null,"errorMessage":"Tag operand {0} not supported","messagePattern":"Tag operand (.+?) not supported","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"vector-stores/spring-ai-redis-store/src/main/java/org/springframework/ai/vectorstore/redis/RedisFilterExpressionConverter.java","lineNumber":185,"sourceCode":"\t * {@code [}, {@code ]}, {@code -}, and {@code '}.\n\t */\n\tprivate String escapeTagValue(String value) {\n\t\tStringBuilder sb = new StringBuilder(value.length());\n\t\tfor (int i = 0; i < value.length(); i++) {\n\t\t\tchar c = value.charAt(i);\n\t\t\tswitch (c) {\n\t\t\t\tcase '\\\\', '$', '|', '{', '}', '(', ')', '[', ']', '-', '\\'' -> sb.append('\\\\').append(c);\n\t\t\t\tdefault -> sb.append(c);\n\t\t\t}\n\t\t}\n\t\treturn sb.toString();\n\t}\n\n\tprivate String tagValueDelimiter(Expression expression) {\n\t\treturn switch (expression.type()) {\n\t\t\tcase IN -> \" | \";\n\t\t\tcase EQ -> \" \";\n\t\t\tdefault -> throw new UnsupportedOperationException(\n\t\t\t\t\tMessageFormat.format(\"Tag operand {0} not supported\", expression.type()));\n\t\t};\n\t}\n\n\tprivate Numeric numeric(Expression expression, Value value) {\n\t\treturn switch (expression.type()) {\n\t\t\tcase EQ -> new Numeric(inclusive(value), inclusive(value));\n\t\t\tcase GT -> new Numeric(exclusive(value), NumericBoundary.POSITIVE_INFINITY);\n\t\t\tcase GTE -> new Numeric(inclusive(value), NumericBoundary.POSITIVE_INFINITY);\n\t\t\tcase LT -> new Numeric(NumericBoundary.NEGATIVE_INFINITY, exclusive(value));\n\t\t\tcase LTE -> new Numeric(NumericBoundary.NEGATIVE_INFINITY, inclusive(value));\n\t\t\tdefault -> throw new UnsupportedOperationException(\n\t\t\t\t\tMessageFormat.format(\"Expression type {0} not supported for numeric fields\", expression.type()));\n\t\t};\n\t}\n\n\tprivate NumericBoundary inclusive(Value value) {\n\t\tif (!(value.value() instanceof Number)) {","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/vector-stores/spring-ai-redis-store/src/main/java/org/springframework/ai/vectorstore/redis/RedisFilterExpressionConverter.java#L167-L203","documentation":"tagValueDelimiter maps a filter expression type to the RediSearch TAG-list delimiter: IN uses ' | ', EQ uses ' '. Any other operand (NE, GT, LT, NIN, etc.) against a TAG field cannot be expressed with tag delimiters, so the converter throws UnsupportedOperationException 'Tag operand {0} not supported'.","triggerScenarios":"Using ne(), gt(), lt(), gte(), lte() or nin() on a metadata field registered as MetadataField.tag(...), e.g. Filter.expr(\"status\").ne(\"done\").","commonSituations":"Assuming TAG fields behave like text/numeric fields and applying range or inequality filters; migrating filters written for NUMERIC fields onto TAG fields.","solutions":["Use only EQ or IN on TAG fields (e.g. status eq \"done\" or status in [\"a\",\"b\"])","Re-register the field as MetadataField.numeric(...) if range comparisons are required (values must be numeric)","Implement inequality by excluding in application code after an IN query","Model negation as IN of the allowed set instead of NE/NIN on a tag"],"exampleFix":"// before\nFilter.expr(\"status\").ne(\"done\"); // TAG field\n// after\nFilter.expr(\"status\").in(List.of(\"open\", \"pending\"));","handlingStrategy":"validation","validationCode":"if (field.fieldType() == TAG && !(expr.type() == EQ || expr.type() == IN)) throw new UnsupportedOperationException(\"TAG fields support only EQ/IN, got: \" + expr.type());","typeGuard":"static boolean isTagSafeOperand(ExpressionType t) { return t == ExpressionType.EQ || t == ExpressionType.IN; }","tryCatchPattern":"try { vectorStore.similaritySearch(request); } catch (UnsupportedOperationException e) { if (e.getMessage().contains(\"Tag operand\")) { /* rewrite filter to IN/EQ */ } else throw e; }","preventionTips":["Restrict TAG-field filters to eq() and in()","Use NUMERIC fields for range/inequality filters","Document which metadata keys are TAG vs NUMERIC in your schema"],"tags":["redis","filter-expression","tag-field","unsupported-operand","spring-ai"],"backgroundTag":"unsupported-operation","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}