pandas-dev/pandas · error · SyntaxError

left hand side of an assignment must be a single name

Error message

left hand side of an assignment must be a single name

What it means

Raised by visit_Assign() when the single target of an assignment is not an ast.Name node — i.e., the left-hand side is not a bare identifier. pandas eval only supports assigning to a simple column name (e.g., 'c = a + b'); assigning to an attribute ('df.c = 1'), a subscript ('df["c"] = 1'), or any complex lvalue is rejected because the assigner must be a single resolvable name.

Solutions

  1. Use a bare column name on the left: df.eval('new_col = col_a + col_b').
  2. For attribute or index assignment, do it outside eval: df.new_col = df['col_a'] + df['col_b'].

Example fix

// before
df.eval('df.new_col = col_a + col_b')

// after
df.eval('new_col = col_a + col_b')
Defensive patterns

Strategy: validation

Validate before calling

import ast
def lhs_is_simple_name(expr: str) -> bool:
    try:
        tree = ast.parse(expr, mode='exec')
    except SyntaxError:
        return True  # let eval raise its own error
    for node in tree.body:
        if isinstance(node, ast.Assign):
            for t in node.targets:
                if not isinstance(t, ast.Name):
                    return False
    return True
if not lhs_is_simple_name(expr):
    raise ValueError('Assignment lhs must be a bare column name')
df.eval(expr)

Try / catch

try:
    df.eval(expr)
except SyntaxError as e:
    if 'single name' in str(e):
        # do assignment outside eval
        ...

Prevention

When it happens

Trigger: df.eval('df.new_col = col_a + col_b') (attribute on lhs); df.eval('a[0] = 1') (subscript lhs); df.eval('(a) = 1') (parenthesized, though ast may normalize some of these).

Common situations: Trying to assign to nested attributes or indexed locations inside the eval string; confusing DataFrame.eval (where lhs is a column name) with general Python assignment.

Related errors


AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11). Data as JSON: /api/errors/d7b62d8d83b0188b. Report an issue: GitHub.

Appendix: source

Thrown at pandas/core/computation/expr.py:626

        if step is not None:
            step = self.visit(step).value

        return slice(lower, upper, step)

    def visit_Assign(self, node, **kwargs):
        """
        support a single assignment node, like

        c = a + b

        set the assigner at the top level, must be a Name node which
        might or might not exist in the resolvers

        """
        if len(node.targets) != 1:
            raise SyntaxError("can only assign a single expression")
        if not isinstance(node.targets[0], ast.Name):
            raise SyntaxError("left hand side of an assignment must be a single name")
        if self.env.target is None:
            raise ValueError("cannot assign without a target object")

        try:
            assigner = self.visit(node.targets[0], **kwargs)
        except UndefinedVariableError:
            assigner = node.targets[0].id

        self.assigner = getattr(assigner, "name", assigner)
        if self.assigner is None:
            raise SyntaxError(
                "left hand side of an assignment must be a single resolvable name"
            )

        return self.visit(node.value, **kwargs)

    def visit_Attribute(self, node, **kwargs):
        attr = node.attr

View on GitHub (pinned to 3b7651241d)