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

  1. Inline the value as a literal: "lambda x: x.age > 18" instead of referencing a bare name.
  2. If you need parameterization, build the string with the literal substituted in (and keep it under max_filter_source_length=2048).
  3. Prefer passing a Python callable (a real lambda object) in options.filter rather than a string; callables bypass AST validation entirely.
  4. 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

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


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/7c574880073187b8. Report an issue: GitHub.