{"record":{"id":"e8fe5365b2bba649","repo":"pandas-dev/pandas","slug":"invalid-attribute-context-ctx-name","errorCode":null,"errorMessage":"Invalid Attribute context {ctx.__name__}","messagePattern":"Invalid Attribute context (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"pandas/core/computation/pytables.py","lineNumber":520,"sourceCode":"        ctx = type(node.ctx)\n        if ctx == ast.Load:\n            # resolve the value\n            resolved = self.visit(value)\n\n            # try to get the value to see if we are another expression\n            try:\n                resolved = resolved.value\n            except AttributeError:\n                pass\n\n            try:\n                return self.term_type(getattr(resolved, attr), self.env)\n            except AttributeError:\n                # something like datetime.datetime where scope is overridden\n                if isinstance(value, ast.Name) and value.id == attr:\n                    return resolved\n\n        raise ValueError(f\"Invalid Attribute context {ctx.__name__}\")\n\n    def translate_In(self, op):\n        return ast.Eq() if isinstance(op, ast.In) else op\n\n    def _rewrite_membership_op(self, node, left, right):\n        return self.visit(node.op), node.op, left, right\n\n\ndef _validate_where(w):\n    \"\"\"\n    Validate that the where statement is of the right type.\n\n    The type may either be String, Expr, or list-like of Exprs.\n\n    Parameters\n    ----------\n    w : String term expression, Expr, or list-like of Exprs.\n","sourceCodeStart":502,"sourceCodeEnd":538,"githubUrl":"https://github.com/pandas-dev/pandas/blob/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/computation/pytables.py#L502-L538","documentation":"Raised by PyTablesExprVisitor.visit_Attribute when an AST Attribute node carries a ctx other than ast.Load (e.g. Store or Del). The pytables query visitor only knows how to read attribute values, so a non-Load attribute access is treated as invalid. In practice HDFStore.select(where=...) parses the query in eval mode, which yields Load contexts, so this is an internal guard against malformed/constructed expression trees rather than something users hit through the documented API.","triggerScenarios":"Constructing a PyTablesExprVisitor and feeding it an ast.Attribute node whose .ctx is ast.Store or ast.Del; passing a hand-built AST (not a plain query string) into the pytables expression path; any code path that mutates node.ctx on an attribute before the visitor runs.","commonSituations":"Almost never seen from the public pandas API because df.query / HDFStore.select parse strings with ast.parse(mode='eval'). May surface in tests, forks, or code that rewrites AST nodes (e.g. swapping ctx) before evaluation.","solutions":["Pass the where clause as a plain string (e.g. HDFStore.select(key, where='index >= 5')) so it is parsed in eval mode and attributes get ast.Load context.","If you are building/transforming AST nodes for a pytables query, ensure every ast.Attribute uses ctx=ast.Load() before handing the tree to the visitor.","Avoid attribute-assignment or deletion syntax in a where expression; pytables queries are read-only predicates."],"exampleFix":"// before\nnode = ast.Attribute(value=ast.Name(id='df', ctx=ast.Store()), attr='A', ctx=ast.Store())\nvisitor.visit(node)  # raises: Invalid Attribute context Store\n\n// after\nnode = ast.Attribute(value=ast.Name(id='df', ctx=ast.Load()), attr='A', ctx=ast.Load())\nvisitor.visit(node)","handlingStrategy":"validation","validationCode":"import ast\nnode = <your attribute ast node>\nif not isinstance(getattr(node, 'ctx', None), ast.Load):\n    raise ValueError(f'attribute node must use ast.Load ctx, got {type(node.ctx).__name__}')","typeGuard":"import ast\n\ndef is_load_attribute(node) -> bool:\n    return isinstance(node, ast.Attribute) and isinstance(node.ctx, ast.Load)","tryCatchPattern":"try:\n    visitor.visit(attribute_node)\nexcept ValueError as err:\n    if 'Invalid Attribute context' in str(err):\n        # rewrite the node with ast.Load ctx or fall back to a string query\n        ...\n    raise","preventionTips":["Always parse pytables where clauses from strings via ast.parse(mode='eval') so ctx is Load.","Never mutate node.ctx on attribute nodes before visiting.","Keep pytables queries read-only; do not attempt assignment/deletion semantics."],"tags":["pytables","hdf5","ast","expression-evaluation","internal-guard"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}