microsoft/semantic-kernel · error · VectorStoreOperationException
Use of name '{node.id}' is not allowed in filter expressions
Error message
Use of name '{node.id}' is not allowed in filter expressions. Only the lambda parameter(s) ({', '.join(lambda_param_names)}) can be used. What it means
Thrown by InMemoryCollection._parse_and_validate_filter (in_memory.py:790) while walking the AST of a string filter. The sandbox only permits references to the lambda's own parameter names; any other bare name is rejected so untrusted filter strings cannot reach globals or builtins. The offending name and the allowed parameter names are both included in the message.
Source
Thrown at python/semantic_kernel/connectors/in_memory.py:790
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."
)
# For Attribute nodes, validate that dangerous dunder attributes are not accessed
if isinstance(node, ast.Attribute) and node.attr in self.blocked_filter_attributes:
raise VectorStoreOperationException(
f"Access to attribute '{node.attr}' is not allowed in filter expressions. "
"This attribute could be used to escape the filter sandbox."
)
# For Name nodes, only allow the lambda parameter
if isinstance(node, ast.Name) and node.id not in lambda_param_names:
raise VectorStoreOperationException(
f"Use of name '{node.id}' is not allowed in filter expressions. "
f"Only the lambda parameter(s) ({', '.join(lambda_param_names)}) can be used."
)
# For Call nodes, validate that only allowed functions are called
if isinstance(node, ast.Call):
func_name: str
if isinstance(node.func, ast.Name):
func_name = node.func.id
elif isinstance(node.func, ast.Attribute):
func_name = node.func.attr
else:
raise VectorStoreOperationException(
f"Call target node type '{type(node.func).__name__}' is not allowed in filter expressions. "
"Only direct function and method calls are supported."
)
if func_name not in self.allowed_filter_functions:View on GitHub (pinned to c028a0c7dc)
Solutions
- Inline the value as a literal: "lambda x: x.age > 18" instead of referencing a bare name.
- If you need parameterization, build the string with the literal substituted in (and keep it under max_filter_source_length=2048).
- Prefer passing a Python callable (a real lambda object) in options.filter rather than a string; callables bypass AST validation entirely.
- If the name must be allowed, subclass InMemoryCollection and extend validation, but never widen this for untrusted input.
Example fix
# before MIN_AGE = 18 options = VectorSearchOptions(filter="lambda x: x.age > MIN_AGE") # after options = VectorSearchOptions(filter="lambda x: x.age > 18") # or pass a callable (no AST sandbox): options = VectorSearchOptions(filter=lambda x: x.age > MIN_AGE)
Defensive patterns
Strategy: validation
Validate before calling
import ast
def validate_filter_names(filter_str: str, allowed_param_names: set[str]) -> list[str]:
tree = ast.parse(filter_str, mode="eval")
problems = []
for node in ast.walk(tree):
if isinstance(node, ast.Name) and node.id not in allowed_param_names:
problems.append(node.id)
return problems
# call before constructing VectorSearchOptions
bad = validate_filter_names("lambda x: x.age > MIN_AGE", {"x"})
assert not bad, f"filter references disallowed names: {bad}" Type guard
def is_safe_string_filter(filter_str: str) -> bool:
try:
tree = ast.parse(filter_str, mode="eval")
except SyntaxError:
return False
if not (isinstance(tree, ast.Expression) and isinstance(tree.body, ast.Lambda)):
return False
params = {a.arg for a in tree.body.args.args}
return all(
not (isinstance(n, ast.Name) and n.id not in params)
for n in ast.walk(tree)
) Try / catch
from semantic_kernel.exceptions.vector_store_exceptions import VectorStoreOperationException
try:
results = await collection.search(options)
except VectorStoreOperationException as ex:
if "not allowed in filter expressions" in str(ex):
# fix the filter string and retry with a sanitized literal
... Prevention
- Prefer passing a real Python lambda (callable) in options.filter instead of a string; callables bypass the AST sandbox.
- Keep string filters to a single-parameter lambda referencing only that parameter.
- Never interpolate external variable names into a string filter; inline their values as literals.
- Validate untrusted filter strings with an AST walk before passing them to search.
When it happens
Trigger: Passing VectorSearchOptions.filter (or _get_filtered_records) a string lambda that references an external symbol, e.g. "lambda x: x.age > MIN_AGE" where MIN_AGE is not a lambda parameter. A single-parameter lambda is the expected shape, so any second identifier fails the ast.Name check at in_memory.py:789.
Common situations: Trying to parameterize a string filter with a Python variable instead of a literal; copy-pasting a lambda that worked in a real Python scope; migrating a filter that used a module-level constant; forgetting that the sandbox has no globals namespace.
Related errors
- Call target node type '{type(node.func).__name__}' is not al
- AST node type '{type(node).__name__}' is not supported durin
- Function '{func_name}' is not allowed in filter expressions.
- Unsupported operator: {type(op)}
- Invert operation is not supported.
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/7c574880073187b8.
Report an issue: GitHub.