microsoft/semantic-kernel · error · VectorStoreOperationException

Binary operator '{type(node.op).__name__}' is not allowed in

Error message

Binary operator '{type(node.op).__name__}' is not allowed in filter expressions.

What it means

_eval_BinOp supports only Add, Sub, Mult, Div, Mod, and FloorDiv. Any other binary operator (Pow '**', LShift/RShift, BitAnd/BitOr/BitXor, MatMult) raises VectorStoreOperationException. The static allowlist covers exactly those six operators, so others are rejected at parse time first; the eval-time branch is the safety net for subclass-widened allowlists.

Source

Thrown at python/semantic_kernel/connectors/in_memory.py:270

    def _eval_BinOp(self, node: ast.BinOp, context: Mapping[str, Any]) -> Any:
        """Evaluate a binary operator."""
        left = self.evaluate(node.left, context)
        right = self.evaluate(node.right, context)

        if isinstance(node.op, ast.Add):
            return self._safe_add(left, right)
        if isinstance(node.op, ast.Sub):
            return self._safe_numeric_operation(node.op, left, right, lambda a, b: a - b)
        if isinstance(node.op, ast.Mult):
            return self._safe_mult(left, right)
        if isinstance(node.op, ast.Div):
            return self._safe_numeric_operation(node.op, left, right, lambda a, b: a / b)
        if isinstance(node.op, ast.Mod):
            return self._safe_numeric_operation(node.op, left, right, lambda a, b: a % b)
        if isinstance(node.op, ast.FloorDiv):
            return self._safe_numeric_operation(node.op, left, right, lambda a, b: a // b)

        raise VectorStoreOperationException(
            f"Binary operator '{type(node.op).__name__}' is not allowed in filter expressions."
        )

    def _eval_Call(self, node: ast.Call, context: Mapping[str, Any]) -> Any:
        """Evaluate a function or method call."""
        args = [self.evaluate(arg, context) for arg in node.args]

        if isinstance(node.func, ast.Name):
            try:
                func = self._direct_call_functions[node.func.id]
            except KeyError as e:
                raise VectorStoreOperationException(
                    f"Function '{node.func.id}' is only supported as a method call in filter expressions."
                ) from e
            return func(*args)

        if isinstance(node.func, ast.Attribute):
            target = self.evaluate(node.func.value, context)

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Rewrite without unsupported operators (e.g. x.a * x.a instead of x.a ** 2).
  2. Do not add Pow/shift/bitwise operator nodes to allowed_filter_ast_nodes without a matching evaluator branch.

Example fix

# before
VectorSearchOptions(filter=lambda x: x.a ** 2 > 100)  # Pow -> static reject (or [1316])

# after
VectorSearchOptions(filter=lambda x: x.a * x.a > 100)
Defensive patterns

Strategy: validation

Validate before calling

import ast
ALLOWED = {ast.Add, ast.Sub, ast.Mult, ast.Div, ast.Mod, ast.FloorDiv}
def uses_only_allowed_binops(filter_str: str) -> None:
    for node in ast.walk(ast.parse(filter_str, mode='eval')):
        if isinstance(node, ast.BinOp) and type(node.op) not in ALLOWED:
            raise ValueError(f"binary operator {type(node.op).__name__} is not allowed in filters")

Prevention

When it happens

Trigger: A filter like lambda x: x.a ** 2, lambda x: x.a | x.b, or lambda x: x.a << 2; reaches the evaluator only if the extra operator nodes were added to allowed_filter_ast_nodes.

Common situations: Using power or bitwise operations in a computed comparison; attempting set-like ops with bitwise-or.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/337b5dbf405a980b. Report an issue: GitHub.