{"record":{"id":"d65d7cb3944dfac4","repo":"spring-projects/spring-ai","slug":"not-supported-expression-type-expressiontype","errorCode":null,"errorMessage":"Not supported expression type: {expressionType}","messagePattern":"Not supported expression type: (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"vector-stores/spring-ai-couchbase-store/src/main/java/org/springframework/ai/vectorstore/couchbase/CouchbaseAiSearchFilterExpressionConverter.java","lineNumber":57,"sourceCode":"\t\t}\n\t\telse {\n\t\t\tcontext.append(\"NULL\");\n\t\t}\n\t}\n\n\tprivate String getOperationSymbol(Expression exp) {\n\t\treturn switch (exp.type()) {\n\t\t\tcase AND -> \" AND \";\n\t\t\tcase OR -> \" OR \";\n\t\t\tcase EQ -> \" == \";\n\t\t\tcase NE -> \" != \";\n\t\t\tcase LT -> \" < \";\n\t\t\tcase LTE -> \" <= \";\n\t\t\tcase GT -> \" > \";\n\t\t\tcase GTE -> \" >= \";\n\t\t\tcase IN -> \" IN \";\n\t\t\tcase NIN -> \" NOT IN \";\n\t\t\tdefault -> throw new RuntimeException(\"Not supported expression type: \" + exp.type());\n\t\t};\n\t}\n\n\t@Override\n\tprotected void doKey(Key key, StringBuilder context) {\n\t\tcontext.append(\"metadata.\");\n\t\tvar identifier = key.key();\n\t\t// Couchbase N1QL/SQL++ uses backtick-quoted identifiers.\n\t\t// Within backticks, the only character needing escaping is the backtick\n\t\t// itself (doubled as ``).\n\t\tcontext.append('`');\n\t\tfor (int i = 0; i < identifier.length(); i++) {\n\t\t\tchar c = identifier.charAt(i);\n\t\t\tif (c == '`') {\n\t\t\t\tcontext.append(\"``\");\n\t\t\t}\n\t\t\telse {\n\t\t\t\tcontext.append(c);","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/vector-stores/spring-ai-couchbase-store/src/main/java/org/springframework/ai/vectorstore/couchbase/CouchbaseAiSearchFilterExpressionConverter.java#L39-L75","documentation":"CouchbaseAiSearchFilterExpressionConverter.getOperationSymbol maps supported filter types to N1QL operator strings. Types outside GT, GTE, LT, LTE, IN, NIN (and the equality/comparison set handled before it) hit the default branch and throw this RuntimeException. It is called from doExpression during filter-to-N1QL conversion.","triggerScenarios":"Passing a filter expression with an unsupported type (e.g. NOT, CONTAINS) to a Couchbase vector store search or delete; the N1QL converter has no operator symbol for it.","commonSituations":"Filters parsed from text with negation operators; reusing filter DSLs from other vector stores; metadata array searches using CONTAINS.","solutions":["Rewrite NOT using De Morgan's laws with supported operators (NE, AND, OR).","Replace CONTAINS/CONTAINS_KEY with EQ/IN where possible, or filter array metadata client-side after retrieval.","Extend getOperationSymbol to emit N1QL for the missing operator (e.g. \" NOT IN \" patterns already exist for NIN)."],"exampleFix":"// before\nnew FilterExpressionBuilder().not(new FilterExpressionBuilder().eq(\"metadata.type\", \"tmp\")).build();\n// after\nnew FilterExpressionBuilder().ne(\"metadata.type\", \"tmp\").build();","handlingStrategy":"validation","validationCode":"Set<Filter.ExpressionType> N1QL_OK = Set.of(EQ, NE, GT, GTE, LT, LTE, IN, NIN, AND, OR);\nvoid verify(Filter.Expression e) {\n  if (!N1QL_OK.contains(e.type())) throw new IllegalArgumentException(\"Unsupported for Couchbase: \" + e.type());\n  if (e.left() instanceof Filter.Expression l) verify(l);\n  if (e.right() instanceof Filter.Expression r) verify(r);\n}","typeGuard":"boolean couchbaseSafe(Filter.Expression e) {\n  return e.type() != NOT && e.type() != CONTAINS && e.type() != CONTAINS_KEY;\n}","tryCatchPattern":"try {\n  vectorStore.similaritySearch(request);\n} catch (RuntimeException e) {\n  if (e.getMessage().startsWith(\"Not supported expression type\")) {\n    // rewrite filter without the unsupported operator and retry\n  }\n}","preventionTips":["Replace NOT/CONTAINS filters with supported NE/IN/NIN combinations before querying Couchbase.","Share an operator allow-list across vector store adapters to catch misuse early.","Add unit tests that render every operator your app can emit through this converter."],"tags":["couchbase","filter-expression","unsupported-operation","n1ql","vector-store"],"backgroundTag":"unsupported-enum-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"}