{"record":{"id":"04cffa1276496d0d","repo":"microsoft/semantic-kernel","slug":"ast-node-type-type-node-name-is-not-suppo","errorCode":null,"errorMessage":"AST node type '{type(node).__name__}' is not supported during filter evaluation.","messagePattern":"AST node type '(.+?)' is not supported during filter evaluation\\.","errorType":"exception","errorClass":"VectorStoreOperationException","httpStatus":null,"severity":"error","filePath":"python/semantic_kernel/connectors/in_memory.py","lineNumber":138,"sourceCode":"\n    def __init__(\n        self,\n        *,\n        direct_call_functions: dict[str, Callable[..., Any]],\n        blocked_attributes: set[str],\n        max_literal_collection_size: int,\n        max_sequence_repeat_size: int,\n    ):\n        self._direct_call_functions = direct_call_functions\n        self._blocked_attributes = blocked_attributes\n        self._max_literal_collection_size = max_literal_collection_size\n        self._max_sequence_repeat_size = max_sequence_repeat_size\n\n    def evaluate(self, node: ast.AST, context: Mapping[str, Any]) -> Any:\n        \"\"\"Evaluate a supported AST node.\"\"\"\n        evaluator = getattr(self, f\"_eval_{type(node).__name__}\", None)\n        if evaluator is None:\n            raise VectorStoreOperationException(\n                f\"AST node type '{type(node).__name__}' is not supported during filter evaluation.\"\n            )\n        return evaluator(node, context)\n\n    def _eval_Constant(self, node: ast.Constant, context: Mapping[str, Any]) -> Any:\n        \"\"\"Evaluate a constant literal.\"\"\"\n        del context\n        if isinstance(node.value, str) and len(node.value) > self._max_literal_collection_size:\n            raise VectorStoreOperationException(\n                \"String literals in filter expressions exceed the maximum allowed size.\"\n            )\n        return node.value\n\n    def _eval_Name(self, node: ast.Name, context: Mapping[str, Any]) -> Any:\n        \"\"\"Evaluate a variable reference.\"\"\"\n        if node.id not in context:\n            raise VectorStoreOperationException(f\"Use of name '{node.id}' is not allowed in filter expressions.\")\n        return context[node.id]","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/semantic_kernel/connectors/in_memory.py#L120-L156","documentation":"_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).","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"# before\nclass MyCollection(InMemoryCollection):\n    allowed_filter_ast_nodes = InMemoryCollection.allowed_filter_ast_nodes | {ast.IfExp}\n# evaluating 'lambda x: x.a if x.b else x.c' -> [1307]\n\n# after\nclass MyEvaluator(_SafeFilterEvaluator):\n    def _eval_IfExp(self, node, context):\n        return self.evaluate(node.body, context) if self.evaluate(node.test, context) else self.evaluate(node.orelse, context)","handlingStrategy":"validation","validationCode":"import ast\n\ndef supported_node_names(evaluator) -> set[str]:\n    return {n[len('_eval_'):] for n in dir(evaluator) if n.startswith('_eval_')}\n\ndef filter_uses_only_evaluatable(filter_str: str, evaluator) -> None:\n    ok = supported_node_names(evaluator)\n    for node in ast.walk(ast.parse(filter_str, mode='eval')):\n        if type(node).__name__ not in ok and type(node).__name__ not in {\n            'Expression', 'Lambda', 'arguments', 'arg', 'Load',\n            'And', 'Or', 'Not', 'Eq', 'NotEq', 'Lt', 'LtE', 'Gt', 'GtE',\n            'In', 'NotIn', 'Is', 'IsNot', 'Add', 'Sub', 'Mult', 'Div', 'Mod', 'FloorDiv',\n        }:\n            raise ValueError(f\"filter uses unsupported node {type(node).__name__}\")","typeGuard":"def evaluator_handles(evaluator, node: ast.AST) -> bool:\n    return callable(getattr(evaluator, f'_eval_{type(node).__name__}', None))","tryCatchPattern":"from semantic_kernel.exceptions import VectorStoreOperationException\ntry:\n    await collection.search(vector=[...], options=VectorSearchOptions(filter=f))\nexcept VectorStoreOperationException as ex:\n    if 'is not supported during filter evaluation' in str(ex):\n        # rewrite the filter using only built-in supported nodes\n        ...\n    raise","preventionTips":["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."],"tags":["in-memory","filter","ast","sandbox"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}