{"record":{"id":"5d9eec94d9d57f23","repo":"microsoft/semantic-kernel","slug":"attribute-node-func-attr-is-not-callable-in-fi","errorCode":null,"errorMessage":"Attribute '{node.func.attr}' is not callable in filter expressions.","messagePattern":"Attribute '(.+?)' is not callable in filter expressions\\.","errorType":"exception","errorClass":"VectorStoreOperationException","httpStatus":null,"severity":"error","filePath":"python/semantic_kernel/connectors/in_memory.py","lineNumber":302,"sourceCode":"                ) from e\n            return func(*args)\n\n        if isinstance(node.func, ast.Attribute):\n            target = self.evaluate(node.func.value, context)\n            if node.func.attr == \"contains\":\n                if len(args) != 1:\n                    raise VectorStoreOperationException(\"Method 'contains' expects exactly one argument.\")\n                return args[0] in target\n\n            try:\n                func = getattr(target, node.func.attr)\n            except AttributeError as e:\n                raise VectorStoreOperationException(\n                    f\"Method '{node.func.attr}' is not available in filter expressions.\"\n                ) from e\n\n            if not callable(func):\n                raise VectorStoreOperationException(\n                    f\"Attribute '{node.func.attr}' is not callable in filter expressions.\"\n                )\n            return func(*args)\n\n        raise VectorStoreOperationException(\n            f\"Call target node type '{type(node.func).__name__}' is not allowed in filter expressions.\"\n        )\n\n    def _compare(self, operator_node: ast.AST, left: Any, right: Any) -> bool:\n        \"\"\"Evaluate a comparison operator.\"\"\"\n        if isinstance(operator_node, ast.Eq):\n            return left == right\n        if isinstance(operator_node, ast.NotEq):\n            return left != right\n        if isinstance(operator_node, ast.Lt):\n            return left < right\n        if isinstance(operator_node, ast.LtE):\n            return left <= right","sourceCodeStart":284,"sourceCodeEnd":320,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/semantic_kernel/connectors/in_memory.py#L284-L320","documentation":"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.","triggerScenarios":"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()`.","commonSituations":"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.","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."],"exampleFix":"# before\nVectorSearchOptions(filter=\"lambda x: x.items() == [1,2]\")  # field 'items' holds a list\n# after\nVectorSearchOptions(filter=\"lambda x: x['items'] == [1,2]\")  # subscript data access","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    results = await collection.search(search_type=SearchType.VECTOR, options=opts)\nexcept VectorStoreOperationException as e:\n    logger.warning(\"filter rejected: %s\", e.__cause__ or e)\n    results = None","preventionTips":["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."],"tags":["filter","in-memory","vector-store","semantic-kernel","evaluation"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}