{"record":{"id":"58956a7b8ba37c96","repo":"microsoft/semantic-kernel","slug":"unsupported-operator-type-op","errorCode":null,"errorMessage":"Unsupported operator: {type(op)}","messagePattern":"Unsupported operator: (.+?)","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"python/semantic_kernel/connectors/azure_ai_search.py","lineNumber":700,"sourceCode":"                op = node.ops[0]\n                match op:\n                    case ast.In():\n                        return f\"search.ismatch({left}, '{right}')\"\n                    case ast.NotIn():\n                        return f\"not search.ismatch({left}, '{right}')\"\n                    case ast.Eq():\n                        return f\"{left} eq {right}\"\n                    case ast.NotEq():\n                        return f\"{left} ne {right}\"\n                    case ast.Gt():\n                        return f\"{left} gt {right}\"\n                    case ast.GtE():\n                        return f\"{left} ge {right}\"\n                    case ast.Lt():\n                        return f\"{left} lt {right}\"\n                    case ast.LtE():\n                        return f\"{left} le {right}\"\n                raise NotImplementedError(f\"Unsupported operator: {type(op)}\")\n            case ast.BoolOp():\n                op_str = \"and\" if isinstance(node.op, ast.And) else \"or\"\n                return \"(\" + f\" {op_str} \".join([self._lambda_parser(v) for v in node.values]) + \")\"\n            case ast.UnaryOp():\n                match node.op:\n                    case ast.UAdd():\n                        return f\"+{self._lambda_parser(node.operand)}\"\n                    case ast.USub():\n                        return f\"-{self._lambda_parser(node.operand)}\"\n                    case ast.Invert():\n                        raise NotImplementedError(\"Invert operation is not supported.\")\n                    case ast.Not():\n                        return f\"not {self._lambda_parser(node.operand)}\"\n            case ast.Attribute():\n                # Support nested property chains\n                return _parse_attribute_chain(node)\n            case ast.Name():\n                raise NotImplementedError(\"Constants are not supported, make sure to use a value or a attribute.\")","sourceCodeStart":682,"sourceCodeEnd":718,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/semantic_kernel/connectors/azure_ai_search.py#L682-L718","documentation":"Raised at the end of the ast.Compare branch in _lambda_parser when the comparison operator is not one of the handled cases (In, NotIn, Eq, NotEq, Gt, GtE, Lt, LtE). Any other operator that Python can syntactically place in a comparison falls through to NotImplementedError. The OData filter language only supports a subset of Python's comparison operators.","triggerScenarios":"Using 'is' or 'is not' in a filter lambda (e.g. lambda x: x.field is None), which produce ast.Is/ast.IsNot operators that are not mapped. Also theoretically any exotic comparison operator the parser does not handle.","commonSituations":"Writing lambda x: x.field is None or lambda x: x.field is not None instead of == None / != None; idiomatic Python 'is None' checks copied into a filter expression.","solutions":["Replace 'is'/'is not' comparisons with == / != (e.g. lambda x: x.field == None).","Stick to the supported operators: ==, !=, >, >=, <, <=, in, not in.","For null checks use == None / != None, which the parser maps to 'eq null'/'ne null'."],"exampleFix":"// before\noptions.filter = lambda x: x.deleted is True\n\n// after\noptions.filter = lambda x: x.deleted == True","handlingStrategy":"validation","validationCode":"import ast\n\ndef filter_uses_supported_ops(filter_lambda) -> None:\n    supported = {ast.Eq, ast.NotEq, ast.Gt, ast.GtE, ast.Lt, ast.LtE, ast.In, ast.NotIn}\n    tree = ast.parse(ast.getsource(filter_lambda), mode=\"exec\")\n    for node in ast.walk(tree):\n        if isinstance(node, ast.Compare):\n            for op in node.ops:\n                assert type(op) in supported, f\"Unsupported comparison operator: {type(op).__name__}\"\n\nfilter_uses_supported_ops(opts.filter)","typeGuard":null,"tryCatchPattern":"try:\n    res = await collection.search(values=q, options=opts)\nexcept NotImplementedError as e:\n    if \"Unsupported operator\" in str(e):\n        opts.filter = lambda x: x.field == None  # replace 'is None'\n        res = await collection.search(values=q, options=opts)\n    raise","preventionTips":["Use only ==, !=, >, >=, <, <=, in, not in in filter lambdas.","Replace 'is'/'is not' with == / != (e.g. == None for null checks).","Statically lint filter lambdas for unsupported comparison operators."],"tags":["filter","odata","lambda-parser","azure-ai-search"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}