{"record":{"id":"8a6a4e6ad8ecf824","repo":"microsoft/semantic-kernel","slug":"attribute-node-attr-is-not-available-in-filter","errorCode":null,"errorMessage":"Attribute '{node.attr}' is not available in filter expressions.","messagePattern":"Attribute '(.+?)' is not available in filter expressions\\.","errorType":"exception","errorClass":"VectorStoreOperationException","httpStatus":null,"severity":"error","filePath":"python/semantic_kernel/connectors/in_memory.py","lineNumber":168,"sourceCode":"        return node.value\n\n    def _eval_Name(self, node: ast.Name, context: Mapping[str, Any]) -> Any:\n        \"\"\"Evaluate a variable reference.\"\"\"\n        if node.id not in context:\n            raise VectorStoreOperationException(f\"Use of name '{node.id}' is not allowed in filter expressions.\")\n        return context[node.id]\n\n    def _eval_Attribute(self, node: ast.Attribute, context: Mapping[str, Any]) -> Any:\n        \"\"\"Evaluate an attribute access.\"\"\"\n        if node.attr in self._blocked_attributes:\n            raise VectorStoreOperationException(\n                f\"Access to attribute '{node.attr}' is not allowed in filter expressions.\"\n            )\n        value = self.evaluate(node.value, context)\n        try:\n            return ReadOnlyAttributeDict._wrap_value(getattr(value, node.attr))\n        except AttributeError as e:\n            raise VectorStoreOperationException(\n                f\"Attribute '{node.attr}' is not available in filter expressions.\"\n            ) from e\n\n    def _eval_Subscript(self, node: ast.Subscript, context: Mapping[str, Any]) -> Any:\n        \"\"\"Evaluate an index or slice operation.\"\"\"\n        value = self.evaluate(node.value, context)\n        slice_value = self.evaluate(node.slice, context)\n        try:\n            return ReadOnlyAttributeDict._wrap_value(value[slice_value])\n        except Exception as e:\n            raise VectorStoreOperationException(f\"Error evaluating subscript access: {e}\") from e\n\n    def _eval_Slice(self, node: ast.Slice, context: Mapping[str, Any]) -> slice:\n        \"\"\"Evaluate a slice node.\"\"\"\n        lower = self._evaluate_optional(node.lower, context)\n        upper = self._evaluate_optional(node.upper, context)\n        step = self._evaluate_optional(node.step, context)\n        return slice(lower, upper, step)","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/semantic_kernel/connectors/in_memory.py#L150-L186","documentation":"After clearing the blocklist, _eval_Attribute resolves the attribute via getattr(value, node.attr). If the underlying record does not have that attribute, AttributeError is raised and re-wrapped as VectorStoreOperationException. This is the common real-world case (distinct from the 1310 blocklist): the filter names a field that simply is not present on the record.","triggerScenarios":"A filter like lambda x: x.titl == 'foo' (typo), or lambda x: x.nonexistent where the record dict/object has no such key. Records use AttributeDict/ReadOnlyAttributeDict, so missing keys surface as AttributeError here.","commonSituations":"Field-name typo; field renamed in the data model; filter written against a different schema; optional fields absent on some records; mixing attribute and dict access styles.","solutions":["Use the exact field name declared in the data model definition.","Use a safe accessor such as x.get('field') (get is in the allowed function list) or guard with 'field' in x.","Validate filter field names against collection.definition.names before searching."],"exampleFix":"# before\nawait collection.search(vector=[...], options=VectorSearchOptions(filter=lambda x: x.titl == 'foo'))  # typo -> [1311]\n\n# after\nawait collection.search(vector=[...], options=VectorSearchOptions(filter=lambda x: x.title == 'foo'))\n# or safe access: lambda x: x.get('title') == 'foo'","handlingStrategy":"validation","validationCode":"def validate_filter_fields(filter_str: str, valid_field_names: set[str]) -> None:\n    import ast\n    for node in ast.walk(ast.parse(filter_str, mode='eval')):\n        if isinstance(node, ast.Attribute) and node.attr not in valid_field_names and node.attr not in {\n            'get','keys','values','items','contains','lower','upper','strip','startswith','endswith',\n        }:\n            raise ValueError(f\"filter references unknown field '{node.attr}'\")","typeGuard":null,"tryCatchPattern":"from semantic_kernel.exceptions import VectorStoreOperationException\ntry:\n    await collection.search(vector=[...], options=opts)\nexcept VectorStoreOperationException as ex:\n    if 'is not available in filter expressions' in str(ex):\n        # switch to x.get('field') or fix the field name\n        ...\n    raise","preventionTips":["Derive filter field names from the data model definition.","Use x.get('field') for optional fields instead of direct attribute access.","Validate filter attribute names against definition.names before searching."],"tags":["in-memory","filter","data-model"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}