{"record":{"id":"183884434c260288","repo":"microsoft/semantic-kernel","slug":"unsupported-operator-type-op-183884","errorCode":null,"errorMessage":"Unsupported operator: {type(op)}","messagePattern":"Unsupported operator: (.+?)","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"python/semantic_kernel/connectors/chroma.py","lineNumber":399,"sourceCode":"                match op:\n                    case ast.In():\n                        return {left: {\"$in\": right}}  # type: ignore\n                    case ast.NotIn():\n                        return {left: {\"$nin\": right}}  # type: ignore\n                    case ast.Eq():\n                        # Chroma allows short form: {field: value}\n                        return {left: right}  # type: ignore\n                    case ast.NotEq():\n                        return {left: {\"$ne\": right}}  # type: ignore\n                    case ast.Gt():\n                        return {left: {\"$gt\": right}}  # type: ignore\n                    case ast.GtE():\n                        return {left: {\"$gte\": right}}  # type: ignore\n                    case ast.Lt():\n                        return {left: {\"$lt\": right}}  # type: ignore\n                    case ast.LtE():\n                        return {left: {\"$lte\": right}}  # type: ignore\n                raise NotImplementedError(f\"Unsupported operator: {type(op)}\")\n            case ast.BoolOp():\n                op = node.op  # type: ignore\n                values = [self._lambda_parser(v) for v in node.values]\n                if isinstance(op, ast.And):\n                    return {\"$and\": values}\n                if isinstance(op, ast.Or):\n                    return {\"$or\": values}\n                raise NotImplementedError(f\"Unsupported BoolOp: {type(op)}\")\n            case ast.UnaryOp():\n                raise NotImplementedError(\"Unary +, -, ~ and ! are not supported in Chroma filters.\")\n            case ast.Attribute():\n                # Only allow attributes that are in the data model\n                if node.attr not in self.definition.storage_names:\n                    raise VectorStoreOperationException(\n                        f\"Field '{node.attr}' not in data model (storage property names are used).\"\n                    )\n                return node.attr\n            case ast.Name():","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/semantic_kernel/connectors/chroma.py#L381-L417","documentation":"A NotImplementedError raised by _lambda_parser when a filter lambda uses a binary comparison operator that has no Chroma mapping. The code maps ast.Eq, NotEq, Gt, GtE, Lt, LtE (and BoolOp And/Or); any other Compare operator — most notably ast.In / ast.Is / ast.IsNot — falls through to 'raise NotImplementedError(f\"Unsupported operator: {type(op)}\")'. This is part of translating a Python lambda into Chroma's where-filter dict.","triggerScenarios":"Writing a collection filter lambda that uses 'in' (membership), 'is', or 'is not' between a field and a value, e.g. lambda x: x.tag in [\"a\",\"b\"] or lambda x: x.val is None.","commonSituations":"Translating SQL/Pandas-style filters that lean on 'in'; treating Chroma like a document DB with $in support without checking the supported AST node set.","solutions":["Rewrite the filter using only the supported comparisons (==, !=, >, >=, <, <=) combined with 'and'/'or'.","For membership, expand manually: lambda x: (x.tag == \"a\") or (x.tag == \"b\").","For null checks use == None / != None (Eq/NotEq) rather than 'is'."],"exampleFix":"// before\nlambda x: x.tag in [\"a\", \"b\"]\n// after\nlambda x: (x.tag == \"a\") or (x.tag == \"b\")","handlingStrategy":"validation","validationCode":"import ast\nALLOWED = {ast.Eq, ast.NotEq, ast.Gt, ast.GtE, ast.Lt, ast.LtE}\nops = [n.ops[0] for n in ast.walk(ast.parse(filter_lambda_src, mode=\"eval\")) if isinstance(n, ast.Compare)]\nassert all(type(o) in ALLOWED for o in ops), \"Filter uses an unsupported comparison operator\"","typeGuard":"import ast\nALLOWED_CMP = {ast.Eq, ast.NotEq, ast.Gt, ast.GtE, ast.Lt, ast.LtE}\n\ndef filter_uses_only_supported_ops(src: str) -> bool:\n    tree = ast.parse(src, mode=\"eval\")\n    return all(type(o) in ALLOWED_CMP\n               for n in ast.walk(tree) if isinstance(n, ast.Compare)\n               for o in n.ops)","tryCatchPattern":"try:\n    results = await collection.vectorized_search(vector=v, options=VectorSearchOptions(filter=lambda x: x.t in [\"a\",\"b\"]))\nexcept NotImplementedError as e:\n    if \"Unsupported operator\" in str(e):\n        # rewrite filter without 'in'/'is'\n        ...","preventionTips":["Restrict filter lambdas to ==, !=, >, >=, <, <= and and/or.","Expand membership tests into ORed equality.","Use == None instead of 'is None'."],"tags":["chroma","vector-store","filter","lambda","not-implemented"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}