microsoft/semantic-kernel · error · VectorStoreOperationException
Attribute '{node.func.attr}' is not callable in filter expre
Error message
Attribute '{node.func.attr}' is not callable in filter expressions. What it means
Thrown by the runtime safe filter evaluator (_eval_Call, in_memory.py:301-304) when a method-call expression such as `x.foo()` resolves via getattr to an existing attribute that is not callable. The parse-time allowlist can only check node and function names; whether the resolved value is actually callable is only known at evaluation time, so this is a value-level guard.
Source
Thrown at python/semantic_kernel/connectors/in_memory.py:302
) 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
if not callable(func):
raise VectorStoreOperationException(
f"Attribute '{node.func.attr}' is not callable in filter expressions."
)
return func(*args)
raise VectorStoreOperationException(
f"Call target node type '{type(node.func).__name__}' is not allowed in filter expressions."
)
def _compare(self, operator_node: ast.AST, left: Any, right: Any) -> bool:
"""Evaluate a comparison operator."""
if isinstance(operator_node, ast.Eq):
return left == right
if isinstance(operator_node, ast.NotEq):
return left != right
if isinstance(operator_node, ast.Lt):
return left < right
if isinstance(operator_node, ast.LtE):
return left <= rightView on GitHub (pinned to c028a0c7dc)
Solutions
- Rename the data field so it does not collide with an allowlisted method name.
- Use subscript access for data, e.g. `x['items']` instead of calling `x.items()`, when you mean field value not a method.
- Restructure the filter so you only call methods on values you know are the right type (strings for .lower()/.strip(), mappings for .keys()/.values()/.items()).
- Wrap the search in try/except VectorStoreOperationException if the collision is unavoidable and degrade gracefully.
Example fix
# before VectorSearchOptions(filter="lambda x: x.items() == [1,2]") # field 'items' holds a list # after VectorSearchOptions(filter="lambda x: x['items'] == [1,2]") # subscript data access
Defensive patterns
Strategy: try-catch
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
- Avoid naming data fields after allowlisted method names (items, keys, values, get, lower, etc.).
- Prefer subscript access x['field'] for data and reserve method calls for genuine operations.
- Unit-test filters against representative record values before running a search.
When it happens
Trigger: A string lambda filter where a data field name collides with an allowlisted method name (lower, upper, strip, startswith, endswith, contains, get, keys, values, items) but the stored value is a non-callable scalar/sequence. Example: a record has a field `items=[1,2,3]` and the filter is `lambda x: x.items()`.
Common situations: Naming a data model field the same as an allowed method; calling .get()/.keys()/.items()/.lower() on a field whose runtime value is a number or string; copy-pasting dict-style calls onto record fields that hold scalars.
Related errors
- Call target node type '{type(node.func).__name__}' is not al
- Comparison operator '{type(operator_node).__name__}' is not
- Addition in filter expressions is only allowed for numeric v
- Multiplication in filter expressions is only allowed for num
- Sequence repetition in filter expressions exceeds the maximu
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/5d9eec94d9d57f23.
Report an issue: GitHub.