microsoft/semantic-kernel · error · VectorStoreOperationException
Filter string must be a lambda expression, e.g. 'lambda x: x
Error message
Filter string must be a lambda expression, e.g. 'lambda x: x.key == 1'
What it means
Thrown by _parse_and_validate_filter (in_memory.py:759-761) when the string parses successfully but the top-level node is not an ast.Lambda (e.g. a bare expression like '1+1', a function call, an assignment, or an import attempt). Only lambda expressions are accepted as the filter root.
Source
Thrown at python/semantic_kernel/connectors/in_memory.py:760
def _parse_and_validate_filter(self, filter_str: str) -> Callable:
"""Parse and validate a string filter as a lambda expression, then return the callable.
Uses an allowlist approach - only explicitly permitted AST node types and function names
are allowed. This can be customized by overriding `allowed_filter_ast_nodes` and
`allowed_filter_functions` class attributes.
"""
if len(filter_str) > self.max_filter_source_length:
raise VectorStoreOperationException("Filter string exceeds the maximum allowed length.")
try:
tree = ast.parse(filter_str, mode="eval")
except SyntaxError as e:
raise VectorStoreOperationException(f"Filter string is not valid Python: {e}") from e
# Only allow lambda expressions at the top level
if not (isinstance(tree, ast.Expression) and isinstance(tree.body, ast.Lambda)):
raise VectorStoreOperationException(
"Filter string must be a lambda expression, e.g. 'lambda x: x.key == 1'"
)
# Get the lambda parameter name(s) to allow them as valid Name nodes
lambda_node = tree.body
lambda_param_names = {arg.arg for arg in lambda_node.args.args}
lambda_param_order = [arg.arg for arg in lambda_node.args.args]
# Walk the AST to validate all nodes against the allowlist
for node_count, node in enumerate(ast.walk(tree), start=1):
if node_count > self.max_filter_ast_node_count:
raise VectorStoreOperationException("Filter expression exceeds the maximum allowed complexity.")
node_type = type(node)
# Check if the node type is allowed
if node_type not in self.allowed_filter_ast_nodes:
raise VectorStoreOperationException(
f"AST node type '{node_type.__name__}' is not allowed in filter expressions."View on GitHub (pinned to c028a0c7dc)
Solutions
- Wrap the expression in a lambda, e.g. 'lambda x: x.id == 1'.
- Use the lambda parameter (x) to reference the record in attribute or subscript form.
- For non-lambda filter languages, translate them to a Python lambda or pass a callable.
Example fix
# before VectorSearchOptions(filter="x.id == 1") # not a lambda VectorSearchOptions(filter="id eq 1") # OData, not python # after VectorSearchOptions(filter="lambda x: x.id == 1")
Defensive patterns
Strategy: validation
Validate before calling
import ast
def is_lambda_expr(expr: str) -> bool:
tree = ast.parse(expr, mode="eval")
return isinstance(tree, ast.Expression) and isinstance(tree.body, ast.Lambda) Try / catch
try:
results = await collection.search(search_type=SearchType.VECTOR, options=opts)
except VectorStoreOperationException as e:
logger.warning("filter rejected: %s", e.__cause__ or e)
results = None Prevention
- Always start string filters with 'lambda x:'.
- Do not pass OData/SQL filter strings to InMemoryCollection; convert to a Python lambda.
When it happens
Trigger: Passing 'x.id == 1' (no lambda wrapper), a bare expression, a statement, or an attempt like "__import__('os')" whose top level is a Call rather than a Lambda.
Common situations: Forgetting the 'lambda x:' prefix; copying an expression from another store's filter syntax; passing SQL-like or OData strings.
Related errors
- AST node type '{node_type.__name__}' is not allowed in filte
- Call target node type '{type(node.func).__name__}' is not al
- Access to attribute '{node.attr}' is not allowed in filter e
- Access to attribute '{node.attr}' is not allowed in filter e
- Dictionary unpacking is not allowed in filter expressions.
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/6051b4410c7a45e9.
Report an issue: GitHub.