microsoft/semantic-kernel · error · VectorStoreOperationException
Comparison operator '{type(operator_node).__name__}' is not
Error message
Comparison operator '{type(operator_node).__name__}' is not allowed in filter expressions. What it means
Thrown by _compare (in_memory.py:333-335) for a comparison operator outside the handled set (Eq, NotEq, Lt, LtE, Gt, GtE, In, NotIn, Is, IsNot). Defense-in-depth: the parse-time allowlist admits exactly these comparison operators, so this branch is normally only reachable with a custom/relaxed allowlist.
Source
Thrown at python/semantic_kernel/connectors/in_memory.py:333
if isinstance(operator_node, ast.NotEq):
return left != right
if isinstance(operator_node, ast.Lt):
return left < right
if isinstance(operator_node, ast.LtE):
return left <= right
if isinstance(operator_node, ast.Gt):
return left > right
if isinstance(operator_node, ast.GtE):
return left >= right
if isinstance(operator_node, ast.In):
return left in right
if isinstance(operator_node, ast.NotIn):
return left not in right
if isinstance(operator_node, ast.Is):
return left is right
if isinstance(operator_node, ast.IsNot):
return left is not right
raise VectorStoreOperationException(
f"Comparison operator '{type(operator_node).__name__}' is not allowed in filter expressions."
)
def _safe_add(self, left: Any, right: Any) -> Any:
"""Safely evaluate addition."""
if isinstance(left, (int, float)) and isinstance(right, (int, float)):
return left + right
if isinstance(left, str) and isinstance(right, str):
return self._ensure_sequence_result_size(left, right, lambda a, b: a + b)
if isinstance(left, list) and isinstance(right, list):
return self._ensure_sequence_result_size(left, right, lambda a, b: a + b)
if isinstance(left, tuple) and isinstance(right, tuple):
return self._ensure_sequence_result_size(left, right, lambda a, b: a + b)
raise VectorStoreOperationException(
"Addition in filter expressions is only allowed for numeric values and same-type sequences."
)
def _safe_mult(self, left: Any, right: Any) -> Any:View on GitHub (pinned to c028a0c7dc)
Solutions
- Use only the supported comparison operators in filters (==, !=, <, <=, >, >=, in, not in, is, is not).
- Do not extend allowed_filter_ast_nodes with comparison node types the evaluator does not handle.
Example fix
# before # custom allowlist admits an unsupported comparator lambda x: x.a <~ x.b # not real python; a node the evaluator cannot map # after lambda x: x.a <= x.b
Defensive patterns
Strategy: validation
Validate before calling
import ast
SAFE_NODES = {
ast.Expression, ast.Lambda, ast.arguments, ast.arg, ast.Compare, ast.BoolOp,
ast.UnaryOp, ast.And, ast.Or, ast.Not, ast.Eq, ast.NotEq, ast.Lt, ast.LtE,
ast.Gt, ast.GtE, ast.In, ast.NotIn, ast.Is, ast.IsNot, ast.Name, ast.Load,
ast.Attribute, ast.Subscript, ast.Slice, ast.Constant, ast.List, ast.Tuple,
ast.Set, ast.Dict, ast.BinOp, ast.Add, ast.Sub, ast.Mult, ast.Div, ast.Mod,
ast.FloorDiv, ast.Call,
}
def preflight_filter(expr: str, *, max_len: int = 2048, max_nodes: int = 128) -> None:
if len(expr) > max_len:
raise ValueError("filter too long")
try:
tree = ast.parse(expr, mode="eval")
except SyntaxError as e:
raise ValueError(f"invalid python: {e}") from e
if not (isinstance(tree, ast.Expression) and isinstance(tree.body, ast.Lambda)):
raise ValueError("filter must be a lambda expression")
blocked = {"__class__", "__globals__", "__subclasses__", "__builtins__", "__code__"}
for n in ast.walk(tree):
if isinstance(n, ast.Attribute) and n.attr in blocked:
raise ValueError(f"blocked attribute: {n.attr}")
if type(n) not in SAFE_NODES:
raise ValueError(f"disallowed node: {type(n).__name__}")
if sum(1 for _ in ast.walk(tree)) > max_nodes:
raise ValueError("filter too complex")
Try / catch
try:
results = await collection.search(search_type=SearchType.VECTOR, options=opts)
except VectorStoreOperationException as e:
logger.warning("filter rejected: %s", e.__cause__ or e)
results = None Prevention
- Stick to standard comparison operators in filter lambdas.
- Re-test filters after changing the AST allowlist.
When it happens
Trigger: A subclass that adds an exotic comparison node type to allowed_filter_ast_nodes, or a manually constructed filter callable that bypasses parse-time checks and reaches the evaluator with an unsupported comparator.
Common situations: Customizing the evaluator allowlist; future Python AST node additions that are not yet handled.
Related errors
- Attribute '{node.func.attr}' is not callable in filter expre
- Call target node type '{type(node.func).__name__}' is not al
- Addition in filter expressions is only allowed for numeric v
- Multiplication in filter expressions is only allowed for num
- Sequence repetition in filter expressions exceeds the maximu
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/27cb7d62fe4e2f8e.
Report an issue: GitHub.