microsoft/semantic-kernel · error · VectorStoreOperationException
AST node type '{type(node).__name__}' is not supported durin
Error message
AST node type '{type(node).__name__}' is not supported during filter evaluation. What it means
_SafeFilterEvaluator.evaluate dispatches on the AST node class name via getattr(self, '_eval_' + type(node).__name__). If no such handler method exists it raises VectorStoreOperationException. This is the runtime-evaluation counterpart to the static allowed_filter_ast_nodes check; normally the static check rejects unknown node types first, so this fires when the static allowlist was widened by a subclass without adding a matching _eval_* method (an evaluator/validator inconsistency).
Source
Thrown at python/semantic_kernel/connectors/in_memory.py:138
def __init__(
self,
*,
direct_call_functions: dict[str, Callable[..., Any]],
blocked_attributes: set[str],
max_literal_collection_size: int,
max_sequence_repeat_size: int,
):
self._direct_call_functions = direct_call_functions
self._blocked_attributes = blocked_attributes
self._max_literal_collection_size = max_literal_collection_size
self._max_sequence_repeat_size = max_sequence_repeat_size
def evaluate(self, node: ast.AST, context: Mapping[str, Any]) -> Any:
"""Evaluate a supported AST node."""
evaluator = getattr(self, f"_eval_{type(node).__name__}", None)
if evaluator is None:
raise VectorStoreOperationException(
f"AST node type '{type(node).__name__}' is not supported during filter evaluation."
)
return evaluator(node, context)
def _eval_Constant(self, node: ast.Constant, context: Mapping[str, Any]) -> Any:
"""Evaluate a constant literal."""
del context
if isinstance(node.value, str) and len(node.value) > self._max_literal_collection_size:
raise VectorStoreOperationException(
"String literals in filter expressions exceed the maximum allowed size."
)
return node.value
def _eval_Name(self, node: ast.Name, context: Mapping[str, Any]) -> Any:
"""Evaluate a variable reference."""
if node.id not in context:
raise VectorStoreOperationException(f"Use of name '{node.id}' is not allowed in filter expressions.")
return context[node.id]View on GitHub (pinned to c028a0c7dc)
Solutions
- Subclass _SafeFilterEvaluator and add an _eval_<NodeName> method for every node type you added to allowed_filter_ast_nodes.
- Remove the unsupported node from allowed_filter_ast_nodes so the static check rejects it clearly.
- Stick to the built-in supported nodes (Compare, BoolOp, UnaryOp, BinOp, Call, Name, Attribute, Subscript, Constant, list/tuple/set/dict literals).
Example fix
# before
class MyCollection(InMemoryCollection):
allowed_filter_ast_nodes = InMemoryCollection.allowed_filter_ast_nodes | {ast.IfExp}
# evaluating 'lambda x: x.a if x.b else x.c' -> [1307]
# after
class MyEvaluator(_SafeFilterEvaluator):
def _eval_IfExp(self, node, context):
return self.evaluate(node.body, context) if self.evaluate(node.test, context) else self.evaluate(node.orelse, context) Defensive patterns
Strategy: validation
Validate before calling
import ast
def supported_node_names(evaluator) -> set[str]:
return {n[len('_eval_'):] for n in dir(evaluator) if n.startswith('_eval_')}
def filter_uses_only_evaluatable(filter_str: str, evaluator) -> None:
ok = supported_node_names(evaluator)
for node in ast.walk(ast.parse(filter_str, mode='eval')):
if type(node).__name__ not in ok and type(node).__name__ not in {
'Expression', 'Lambda', 'arguments', 'arg', 'Load',
'And', 'Or', 'Not', 'Eq', 'NotEq', 'Lt', 'LtE', 'Gt', 'GtE',
'In', 'NotIn', 'Is', 'IsNot', 'Add', 'Sub', 'Mult', 'Div', 'Mod', 'FloorDiv',
}:
raise ValueError(f"filter uses unsupported node {type(node).__name__}") Type guard
def evaluator_handles(evaluator, node: ast.AST) -> bool:
return callable(getattr(evaluator, f'_eval_{type(node).__name__}', None)) Try / catch
from semantic_kernel.exceptions import VectorStoreOperationException
try:
await collection.search(vector=[...], options=VectorSearchOptions(filter=f))
except VectorStoreOperationException as ex:
if 'is not supported during filter evaluation' in str(ex):
# rewrite the filter using only built-in supported nodes
...
raise Prevention
- When subclassing to allow new AST nodes, add the matching _eval_<NodeName> method too.
- Prefer the built-in supported node set for string filters.
- Unit-test custom evaluators against each node type you allow.
When it happens
Trigger: A subclass adds a node type to allowed_filter_ast_nodes (e.g. ast.IfExp, ast.DictComp, ast.GeneratorExp, ast.Starred, ast.JoinedStr) but does not implement the corresponding _eval_<NodeName> on the evaluator, then a string filter using that construct is evaluated against records.
Common situations: Customizing the filter sandbox to support ternaries or comprehensions; upgrading the library so a previously-added custom node no longer has an evaluator; subclassing InMemoryCollection to relax limits.
Related errors
- Use of name '{node.id}' is not allowed in filter expressions
- Access to attribute '{node.attr}' is not allowed in filter e
- Dictionary unpacking is not allowed in filter expressions.
- Boolean operator '{type(node.op).__name__}' is not allowed i
- Unary 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/04cffa1276496d0d.
Report an issue: GitHub.