microsoft/semantic-kernel · error · NotImplementedError
Unsupported operator: {type(op)}
Error message
Unsupported operator: {type(op)} What it means
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.
Source
Thrown at python/semantic_kernel/connectors/azure_ai_search.py:700
op = node.ops[0]
match op:
case ast.In():
return f"search.ismatch({left}, '{right}')"
case ast.NotIn():
return f"not search.ismatch({left}, '{right}')"
case ast.Eq():
return f"{left} eq {right}"
case ast.NotEq():
return f"{left} ne {right}"
case ast.Gt():
return f"{left} gt {right}"
case ast.GtE():
return f"{left} ge {right}"
case ast.Lt():
return f"{left} lt {right}"
case ast.LtE():
return f"{left} le {right}"
raise NotImplementedError(f"Unsupported operator: {type(op)}")
case ast.BoolOp():
op_str = "and" if isinstance(node.op, ast.And) else "or"
return "(" + f" {op_str} ".join([self._lambda_parser(v) for v in node.values]) + ")"
case ast.UnaryOp():
match node.op:
case ast.UAdd():
return f"+{self._lambda_parser(node.operand)}"
case ast.USub():
return f"-{self._lambda_parser(node.operand)}"
case ast.Invert():
raise NotImplementedError("Invert operation is not supported.")
case ast.Not():
return f"not {self._lambda_parser(node.operand)}"
case ast.Attribute():
# Support nested property chains
return _parse_attribute_chain(node)
case ast.Name():
raise NotImplementedError("Constants are not supported, make sure to use a value or a attribute.")View on GitHub (pinned to c028a0c7dc)
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'.
Example fix
// before options.filter = lambda x: x.deleted is True // after options.filter = lambda x: x.deleted == True
Defensive patterns
Strategy: validation
Validate before calling
import ast
def filter_uses_supported_ops(filter_lambda) -> None:
supported = {ast.Eq, ast.NotEq, ast.Gt, ast.GtE, ast.Lt, ast.LtE, ast.In, ast.NotIn}
tree = ast.parse(ast.getsource(filter_lambda), mode="exec")
for node in ast.walk(tree):
if isinstance(node, ast.Compare):
for op in node.ops:
assert type(op) in supported, f"Unsupported comparison operator: {type(op).__name__}"
filter_uses_supported_ops(opts.filter) Try / catch
try:
res = await collection.search(values=q, options=opts)
except NotImplementedError as e:
if "Unsupported operator" in str(e):
opts.filter = lambda x: x.field == None # replace 'is None'
res = await collection.search(values=q, options=opts)
raise Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Unsupported attribute chain root: {type(current)}
- Invert operation is not supported.
- Constants are not supported, make sure to use a value or a a
- Unsupported constant type: {type(value)}
- Field '{top_level}' not in data model (storage property name
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/58956a7b8ba37c96.
Report an issue: GitHub.