microsoft/semantic-kernel · error · VectorStoreOperationException

Function '{node.func.id}' is only supported as a method call

Error message

Function '{node.func.id}' is only supported as a method call in filter expressions.

What it means

_eval_Call handles bare-name calls (ast.Name func) by looking the name up in _direct_call_functions, which contains only the builtin-style functions callable without a target: len, str, int, float, bool, abs, min, max, sum, any, all. The broader allowed_filter_functions set also includes method names (lower, upper, strip, startswith, endswith, contains, get, keys, values, items) that pass the static check but are NOT direct-callable; calling any of those as a bare name raises VectorStoreOperationException.

Source

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

            return self._safe_numeric_operation(node.op, left, right, lambda a, b: a / b)
        if isinstance(node.op, ast.Mod):
            return self._safe_numeric_operation(node.op, left, right, lambda a, b: a % b)
        if isinstance(node.op, ast.FloorDiv):
            return self._safe_numeric_operation(node.op, left, right, lambda a, b: a // b)

        raise VectorStoreOperationException(
            f"Binary operator '{type(node.op).__name__}' is not allowed in filter expressions."
        )

    def _eval_Call(self, node: ast.Call, context: Mapping[str, Any]) -> Any:
        """Evaluate a function or method call."""
        args = [self.evaluate(arg, context) for arg in node.args]

        if isinstance(node.func, ast.Name):
            try:
                func = self._direct_call_functions[node.func.id]
            except KeyError as e:
                raise VectorStoreOperationException(
                    f"Function '{node.func.id}' is only supported as a method call in filter expressions."
                ) from e
            return func(*args)

        if isinstance(node.func, ast.Attribute):
            target = self.evaluate(node.func.value, context)
            if node.func.attr == "contains":
                if len(args) != 1:
                    raise VectorStoreOperationException("Method 'contains' expects exactly one argument.")
                return args[0] in target

            try:
                func = getattr(target, node.func.attr)
            except AttributeError as e:
                raise VectorStoreOperationException(
                    f"Method '{node.func.attr}' is not available in filter expressions."
                ) from e

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Call methods as methods on the value: lambda x: x.title.startswith('a').
  2. For membership, use the contains special-case (x.tags.contains('a')) or the 'in' operator ('a' in x.tags).
  3. Only use len/str/int/float/bool/abs/min/max/sum/any/all as bare function calls.

Example fix

# before
VectorSearchOptions(filter=lambda x: startswith(x.title, 'a'))  # -> [1317]

# after
VectorSearchOptions(filter=lambda x: x.title.startswith('a'))
Defensive patterns

Strategy: validation

Validate before calling

import ast
DIRECT = {'len','str','int','float','bool','abs','min','max','sum','any','all'}
def bare_calls_are_direct(filter_str: str) -> None:
    for node in ast.walk(ast.parse(filter_str, mode='eval')):
        if isinstance(node, ast.Call) and isinstance(node.func, ast.Name):
            if node.func.id not in DIRECT:
                raise ValueError(f"'{node.func.id}' must be called as a method, e.g. x.value.{node.func.id}(...)")

Try / catch

from semantic_kernel.exceptions import VectorStoreOperationException
try:
    await collection.search(vector=[...], options=opts)
except VectorStoreOperationException as ex:
    if 'only supported as a method call' in str(ex):
        # rewrite startswith(x.f, 'a') -> x.f.startswith('a')
        ...
    raise

Prevention

When it happens

Trigger: A filter that calls a method name as a free function, e.g. lambda x: startswith(x.title, 'a') or lambda x: contains(x.tags, 'a'). These pass static validation (the name is in allowed_filter_functions) but fail at evaluation because they are not in direct_filter_functions.

Common situations: Writing method semantics as functions; porting filter syntax from another style; misunderstanding which names are direct-callable.

Related errors


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