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.

What it means

At evaluation time _eval_Name only resolves identifiers present in the context dict, which contains exactly the lambda parameters. Any other Name raises VectorStoreOperationException. The static parse-time check already rejects names that are not lambda parameters, so this runtime branch is a safety net that fires when the static Name restriction was relaxed or an edge case (e.g. a comprehension variable) slipped through.

Source

Thrown at python/semantic_kernel/connectors/in_memory.py:155

        if evaluator is None:
            raise VectorStoreOperationException(
                f"AST node type '{type(node).__name__}' is not supported during filter evaluation."
            )
        return evaluator(node, context)

    def _eval_Constant(self, node: ast.Constant, context: Mapping[str, Any]) -> Any:
        """Evaluate a constant literal."""
        del context
        if isinstance(node.value, str) and len(node.value) > self._max_literal_collection_size:
            raise VectorStoreOperationException(
                "String literals in filter expressions exceed the maximum allowed size."
            )
        return node.value

    def _eval_Name(self, node: ast.Name, context: Mapping[str, Any]) -> Any:
        """Evaluate a variable reference."""
        if node.id not in context:
            raise VectorStoreOperationException(f"Use of name '{node.id}' is not allowed in filter expressions.")
        return context[node.id]

    def _eval_Attribute(self, node: ast.Attribute, context: Mapping[str, Any]) -> Any:
        """Evaluate an attribute access."""
        if node.attr in self._blocked_attributes:
            raise VectorStoreOperationException(
                f"Access to attribute '{node.attr}' is not allowed in filter expressions."
            )
        value = self.evaluate(node.value, context)
        try:
            return ReadOnlyAttributeDict._wrap_value(getattr(value, node.attr))
        except AttributeError as e:
            raise VectorStoreOperationException(
                f"Attribute '{node.attr}' is not available in filter expressions."
            ) from e

    def _eval_Subscript(self, node: ast.Subscript, context: Mapping[str, Any]) -> Any:
        """Evaluate an index or slice operation."""

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Inline the constant into the filter body: lambda x: x.score > 10.
  2. Keep the static Name restriction intact so only lambda parameters are referenced.
  3. If you must parameterize, rebuild the filter string with the value interpolated before parsing.

Example fix

# before
THRESHOLD = 10
await collection.search(vector=[...], options=VectorSearchOptions(filter=lambda x: x.score > THRESHOLD))  # -> [1309]

# after
await collection.search(vector=[...], options=VectorSearchOptions(filter=lambda x: x.score > 10))
Defensive patterns

Strategy: validation

Validate before calling

import ast

def has_no_free_names(filter_str: str) -> None:
    tree = ast.parse(filter_str, mode='eval')
    assert isinstance(tree.body, ast.Lambda)
    params = {a.arg for a in tree.body.args.args}
    allowed_funcs = {'len','str','int','float','bool','abs','min','max','sum','any','all'}
    for node in ast.walk(tree):
        if isinstance(node, ast.Name) and node.id not in params and node.id not in allowed_funcs:
            raise ValueError(f"filter references non-parameter name '{node.id}'; inline it instead")

Try / catch

from semantic_kernel.exceptions import VectorStoreOperationException
try:
    await collection.search(vector=[...], options=opts)
except VectorStoreOperationException as ex:
    if 'is not allowed in filter expressions' in str(ex) and 'name' in str(ex):
        # inline the referenced constant and retry
        ...
    raise

Prevention

When it happens

Trigger: A filter referencing a free/global variable such as lambda x: x.score > THRESHOLD where THRESHOLD is a module-level name; this passes static validation only if the static Name check was loosened, then fails at evaluation.

Common situations: Writing a filter that closes over an outer constant instead of inlining it; subclassing to relax the Name allowlist; copying a lambda from elsewhere that depends on enclosing scope.

Related errors


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