microsoft/semantic-kernel · error · VectorStoreOperationException
Unary operator '{type(node.op).__name__}' is not allowed in
Error message
Unary operator '{type(node.op).__name__}' is not allowed in filter expressions. What it means
_eval_UnaryOp handles only ast.Not. Any other unary operator (USub '-', UAdd '+', Invert '~') raises VectorStoreOperationException. The static allowlist only includes ast.Not among unary operators, so USub/UAdd/Invert are rejected at parse time first; this eval-time branch is the safety net if the static allowlist was widened.
Source
Thrown at python/semantic_kernel/connectors/in_memory.py:238
result = self.evaluate(value, context)
return result
if isinstance(node.op, ast.Or):
result = self.evaluate(node.values[0], context)
for value in node.values[1:]:
if result:
return result
result = self.evaluate(value, context)
return result
raise VectorStoreOperationException(
f"Boolean operator '{type(node.op).__name__}' is not allowed in filter expressions."
)
def _eval_UnaryOp(self, node: ast.UnaryOp, context: Mapping[str, Any]) -> Any:
"""Evaluate a unary operator."""
operand = self.evaluate(node.operand, context)
if isinstance(node.op, ast.Not):
return not operand
raise VectorStoreOperationException(
f"Unary operator '{type(node.op).__name__}' is not allowed in filter expressions."
)
def _eval_Compare(self, node: ast.Compare, context: Mapping[str, Any]) -> bool:
"""Evaluate a comparison expression."""
left = self.evaluate(node.left, context)
for operator_node, comparator in zip(node.ops, node.comparators, strict=True):
right = self.evaluate(comparator, context)
if not self._compare(operator_node, left, right):
return False
left = right
return True
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)
View on GitHub (pinned to c028a0c7dc)
Solutions
- Rewrite to avoid unary minus/plus/invert (e.g. compare against a positive literal, or use x.val * -1 only if multiplication is intended).
- Do not add USub/UAdd/Invert to allowed_filter_ast_nodes unless you also handle them in the evaluator.
Example fix
# before VectorSearchOptions(filter=lambda x: -x.val > 1) # USub -> static reject (or [1315] if allowlist widened) # after VectorSearchOptions(filter=lambda x: x.val < -1) # if simple comparison is the goal, adjust the comparison instead
Defensive patterns
Strategy: validation
Validate before calling
import ast
def uses_only_not_unary(filter_str: str) -> None:
for node in ast.walk(ast.parse(filter_str, mode='eval')):
if isinstance(node, ast.UnaryOp) and not isinstance(node.op, ast.Not):
raise ValueError(f"unary operator {type(node.op).__name__} is not allowed in filters") Prevention
- Avoid unary minus/plus/invert in filters; restructure the comparison.
- Do not add USub/UAdd/Invert to allowed_filter_ast_nodes.
When it happens
Trigger: A filter like lambda x: -x.val > 1 or lambda x: ~x.flags; these reach the evaluator only if ast.USub/ast.UAdd/ast.Invert were added to allowed_filter_ast_nodes by a subclass.
Common situations: Writing arithmetic negation or bitwise-not in a filter; subclassing to allow more unary operators without an evaluator update.
Related errors
- AST node type '{type(node).__name__}' is not supported durin
- Use of name '{node.id}' is not allowed in filter expressions
- Dictionary unpacking is not allowed in filter expressions.
- Boolean operator '{type(node.op).__name__}' is not allowed i
- Binary operator '{type(node.op).__name__}' is not allowed in
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/d3a56934661ad521.
Report an issue: GitHub.