{"record":{"id":"2e3d6393d231a585","repo":"microsoft/semantic-kernel","slug":"filter-expression-exceeds-the-maximum-allowed-comp","errorCode":null,"errorMessage":"Filter expression exceeds the maximum allowed complexity.","messagePattern":"Filter expression exceeds the maximum allowed complexity\\.","errorType":"exception","errorClass":"VectorStoreOperationException","httpStatus":null,"severity":"error","filePath":"python/semantic_kernel/connectors/in_memory.py","lineNumber":771,"sourceCode":"        try:\n            tree = ast.parse(filter_str, mode=\"eval\")\n        except SyntaxError as e:\n            raise VectorStoreOperationException(f\"Filter string is not valid Python: {e}\") from e\n\n        # Only allow lambda expressions at the top level\n        if not (isinstance(tree, ast.Expression) and isinstance(tree.body, ast.Lambda)):\n            raise VectorStoreOperationException(\n                \"Filter string must be a lambda expression, e.g. 'lambda x: x.key == 1'\"\n            )\n\n        # Get the lambda parameter name(s) to allow them as valid Name nodes\n        lambda_node = tree.body\n        lambda_param_names = {arg.arg for arg in lambda_node.args.args}\n        lambda_param_order = [arg.arg for arg in lambda_node.args.args]\n        # Walk the AST to validate all nodes against the allowlist\n        for node_count, node in enumerate(ast.walk(tree), start=1):\n            if node_count > self.max_filter_ast_node_count:\n                raise VectorStoreOperationException(\"Filter expression exceeds the maximum allowed complexity.\")\n\n            node_type = type(node)\n\n            # Check if the node type is allowed\n            if node_type not in self.allowed_filter_ast_nodes:\n                raise VectorStoreOperationException(\n                    f\"AST node type '{node_type.__name__}' is not allowed in filter expressions.\"\n                )\n\n            # For Attribute nodes, validate that dangerous dunder attributes are not accessed\n            if isinstance(node, ast.Attribute) and node.attr in self.blocked_filter_attributes:\n                raise VectorStoreOperationException(\n                    f\"Access to attribute '{node.attr}' is not allowed in filter expressions. \"\n                    \"This attribute could be used to escape the filter sandbox.\"\n                )\n\n            # For Name nodes, only allow the lambda parameter\n            if isinstance(node, ast.Name) and node.id not in lambda_param_names:","sourceCodeStart":753,"sourceCodeEnd":789,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/semantic_kernel/connectors/in_memory.py#L753-L789","documentation":"Thrown by _parse_and_validate_filter (in_memory.py:770-771) when the number of AST nodes in the filter exceeds max_filter_ast_node_count (default 128). It guards against denial-of-service via enormous or deeply nested expressions and is checked during the allowlist walk.","triggerScenarios":"A filter with deeply nested boolean logic, very long chained comparisons, or huge literal collections that expand the node count past 128.","commonSituations":"Auto-generating filters from large rule sets; combining many conditions with and/or; lowering the node cap.","solutions":["Simplify the filter expression.","Split one large filter into a list of filters (options.filter accepts a list, OR-semantics).","Move large constant data out of the filter and pass it as a callable closure.","Raise max_filter_ast_node_count if the complexity is legitimate."],"exampleFix":"# before\nopts = VectorSearchOptions(filter=\"lambda x: \" + \" or \".join(f\"x.id == {i}\" for i in range(200)))\n# after\nids = set(range(200))\nopts = VectorSearchOptions(filter=lambda x: x.id in ids)","handlingStrategy":"validation","validationCode":"import ast\ndef node_count_within(expr: str, cap: int = 128) -> bool:\n    tree = ast.parse(expr, mode=\"eval\")\n    return sum(1 for _ in ast.walk(tree)) <= cap","typeGuard":null,"tryCatchPattern":"try:\n    results = await collection.search(search_type=SearchType.VECTOR, options=opts)\nexcept VectorStoreOperationException as e:\n    logger.warning(\"filter rejected: %s\", e.__cause__ or e)\n    results = None","preventionTips":["Avoid generating filters with hundreds of OR clauses.","Use membership (in) with a closure set instead of long OR chains.","Split very large filters into a list."],"tags":["filter","in-memory","resource-limits","semantic-kernel"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}