{"record":{"id":"f698c476b67bf720","repo":"spring-projects/spring-ai","slug":"not-supported-expression-type-f698c4","errorCode":null,"errorMessage":"Not supported expression type:","messagePattern":"Not supported expression type:","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"vector-stores/spring-ai-mongodb-atlas-store/src/main/java/org/springframework/ai/vectorstore/mongodb/atlas/MongoDBAtlasFilterExpressionConverter.java","lineNumber":81,"sourceCode":"\t\tcontext.append(getOperationSymbol(expression));\n\t\tcontext.append(\":\");\n\t\tthis.convertOperand(expression.right(), context);\n\t\tcontext.append(\"}}\");\n\t}\n\n\tprivate String getOperationSymbol(Filter.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 -> \"$eq\";\n\t\t\tcase NE -> \"$ne\";\n\t\t\tcase LT -> \"$lt\";\n\t\t\tcase LTE -> \"$lte\";\n\t\t\tcase GT -> \"$gt\";\n\t\t\tcase GTE -> \"$gte\";\n\t\t\tcase IN -> \"$in\";\n\t\t\tcase NIN -> \"$nin\";\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(Filter.Key filterKey, StringBuilder context) {\n\t\tvar identifier = filterKey.key();\n\t\temitJsonValue(\"metadata.\" + identifier, context);\n\t}\n\n\t/**\n\t * Serialize values using JSON serialization for MongoDB Atlas filter expressions.\n\t * Delegates to {@link #emitJsonValue(Object, StringBuilder)} for Jackson-based JSON\n\t * serialization.\n\t * @param value the value to serialize\n\t * @param context the context to append the JSON representation to\n\t */\n\t@Override\n\tprotected void doSingleValue(Object value, StringBuilder context) {","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/vector-stores/spring-ai-mongodb-atlas-store/src/main/java/org/springframework/ai/vectorstore/mongodb/atlas/MongoDBAtlasFilterExpressionConverter.java#L63-L99","documentation":"MongoDBAtlasFilterExpressionConverter.getOperationSymbol maps Spring AI Filter.Op values to MongoDB Atlas comparison operators ($lt, $gt, $in, etc.) and throws a RuntimeException(\"Not supported expression type:\") in the default branch when it encounters an operator it cannot translate to an Atlas Search filter clause.","triggerScenarios":"Passing a Filter.Expression whose Op is not EQ/NE/GT/GTE/LT/LTE/IN/NIN (e.g. LIKE, CONTAINS, or nested unsupported combinators) into a SearchRequest filter expression used with MongoDBAtlasVectorStore.","commonSituations":"Building a filter with string matching ops (LIKE/CONTAINS) which Atlas vector search filters do not support this way; using a newer Filter.Op added to Spring AI but not handled by this converter version; version drift between spring-ai-core and the Atlas store module.","solutions":["Rewrite the filter using only supported operators: EQ, NE, GT, GTE, LT, LTE, IN, NIN.","Replace LIKE/CONTAINS expressions with EQ against an exact value or precompute the match in metadata.","Upgrade spring-ai-mongodb-atlas-store to the latest version for broader operator support.","Implement a custom FilterExpressionConverter extending the Atlas converter to handle the missing op.","Split complex filters into supported compound expressions (AND/OR of supported ops)."],"exampleFix":"// before\nnew FilterExpressionBuilder().like(\"genre\", \"doc\").build();\n// after\nnew FilterExpressionBuilder().eq(\"genre\", \"documentary\").build(); // use supported EQ instead of LIKE","handlingStrategy":"validation","validationCode":"// validate filter ops before passing to Atlas search\nstatic boolean isSupportedOp(Filter.Expression exp) {\n    return switch (exp.type()) {\n        case EQ, NE, GT, GTE, LT, LTE, IN, NIN, AND, OR -> true;\n        default -> false; // LIKE, CONTAINS etc. will throw in the Atlas converter\n    };\n}","typeGuard":"boolean isSupportedFilter(Expression filter) {\n    if (filter instanceof Filter.Expression exp) {\n        return isSupportedOp(exp);\n    }\n    return filter instanceof Filter.Group g && g.expressions().stream().allMatch(MyGuards::isSupportedFilter);\n}","tryCatchPattern":"try {\n    vectorStore.similaritySearch(SearchRequest.builder().query(q).filterExpression(expr).build());\n} catch (RuntimeException e) {\n    if (e.getMessage().startsWith(\"Not supported expression type\")) {\n        throw new IllegalArgumentException(\"Rewrite filter with supported ops: EQ/NE/GT/GTE/LT/LTE/IN/NIN\", e);\n    }\n    throw e;\n}","preventionTips":["Only use EQ, NE, GT, GTE, LT, LTE, IN, NIN and AND/OR combinators in Atlas filter expressions.","Avoid LIKE/CONTAINS ops which the Atlas converter cannot translate.","Keep spring-ai core and the Atlas store module versions aligned.","Unit-test filter expressions against the converter before deploying."],"tags":["mongodb-atlas","filter-expression","unsupported-operator","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-14T11:17:12.474Z"}