pandas-dev/pandas · error · ValueError
Invalid Attribute context
Error message
Invalid Attribute context {type(ctx).__name__} What it means
Raised by visit_Attribute() when the attribute node's context (node.ctx) is not an ast.Load instance. pandas eval only supports reading attributes (Load context, e.g., 'df.col' to read a value); attribute deletion (ast.Del) or attribute storage/assignment (ast.Store) are not supported inside the eval DSL. The message includes the actual context type name for diagnostics.
Solutions
- Use attribute access only for reading: df.eval('col_a + df.col_b') where attributes are read-only.
- For attribute assignment, do it outside eval: df.col_c = df['col_a'] + df['col_b'].
- Restrict eval expressions to Load-context attribute access on resolvable objects.
Example fix
// before # expression that triggers a non-Load attribute context inside eval // after df['col_c'] = df['col_a'] + df['col_b'] # do assignment outside eval
Defensive patterns
Strategy: try-catch
Validate before calling
import ast
def attributes_are_load_only(expr: str) -> bool:
try:
tree = ast.parse(expr, mode='eval')
except SyntaxError:
return True
for node in ast.walk(tree):
if isinstance(node, ast.Attribute) and not isinstance(node.ctx, ast.Load):
return False
return True
if not attributes_are_load_only(expr):
raise ValueError('Attribute store/delete not supported in eval')
df.eval(expr) Try / catch
try:
df.eval(expr)
except ValueError as e:
if 'Invalid Attribute context' in str(e):
# perform attribute assignment outside eval
... Prevention
- Use attributes only for reading values in eval.
- Do attribute assignment/modification outside the eval string.
- Keep eval expressions read-only on attributes.
When it happens
Trigger: Expressions that attempt attribute assignment or deletion inside eval, producing an ast.Store or ast.Del context rather than ast.Load. Rare since most such attempts are caught earlier by visit_Assign's ast.Name check, but reachable through certain complex attribute expressions.
Common situations: Constructing expressions that use attribute syntax in a storing/deleting context; programmatic AST manipulation that produces non-Load attribute nodes.
Related errors
- can only assign a single expression
- left hand side of an assignment must be a single name
- left hand side of an assignment must be a single resolvable…
- only a single expression is allowed
- The '@' prefix is not allowed in top-level eval…
AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11).
Data as JSON: /api/errors/f2bb8fcae06d8e74.
Report an issue: GitHub.
Appendix: source
Thrown at pandas/core/computation/expr.py:665
ctx = node.ctx
if isinstance(ctx, ast.Load):
# resolve the value
visited_value = self.visit(value)
if hasattr(visited_value, "value"):
resolved = visited_value.value
else:
resolved = visited_value(self.env)
try:
v = getattr(resolved, attr)
name = self.env.add_tmp(v)
return self.term_type(name, self.env)
except AttributeError:
# something like datetime.datetime where scope is overridden
if isinstance(value, ast.Name) and value.id == attr:
return resolved
raise
raise ValueError(f"Invalid Attribute context {type(ctx).__name__}")
def visit_Call(self, node, side=None, **kwargs):
if isinstance(node.func, ast.Attribute) and node.func.attr != "__call__":
res = self.visit_Attribute(node.func)
elif not isinstance(node.func, ast.Name):
raise TypeError("Only named functions are supported")
else:
try:
res = self.visit(node.func)
except UndefinedVariableError:
# Check if this is a supported function name
try:
res = FuncNode(node.func.id)
except ValueError:
# Raise original error
raise
if res is None:View on GitHub (pinned to 3b7651241d)