{"record":{"id":"d7b62d8d83b0188b","repo":"pandas-dev/pandas","slug":"left-hand-side-of-an-assignment-must-be-a-single-n","errorCode":null,"errorMessage":"left hand side of an assignment must be a single name","messagePattern":"left hand side of an assignment must be a single name","errorType":"exception","errorClass":"SyntaxError","httpStatus":null,"severity":"error","filePath":"pandas/core/computation/expr.py","lineNumber":626,"sourceCode":"        if step is not None:\n            step = self.visit(step).value\n\n        return slice(lower, upper, step)\n\n    def visit_Assign(self, node, **kwargs):\n        \"\"\"\n        support a single assignment node, like\n\n        c = a + b\n\n        set the assigner at the top level, must be a Name node which\n        might or might not exist in the resolvers\n\n        \"\"\"\n        if len(node.targets) != 1:\n            raise SyntaxError(\"can only assign a single expression\")\n        if not isinstance(node.targets[0], ast.Name):\n            raise SyntaxError(\"left hand side of an assignment must be a single name\")\n        if self.env.target is None:\n            raise ValueError(\"cannot assign without a target object\")\n\n        try:\n            assigner = self.visit(node.targets[0], **kwargs)\n        except UndefinedVariableError:\n            assigner = node.targets[0].id\n\n        self.assigner = getattr(assigner, \"name\", assigner)\n        if self.assigner is None:\n            raise SyntaxError(\n                \"left hand side of an assignment must be a single resolvable name\"\n            )\n\n        return self.visit(node.value, **kwargs)\n\n    def visit_Attribute(self, node, **kwargs):\n        attr = node.attr","sourceCodeStart":608,"sourceCodeEnd":644,"githubUrl":"https://github.com/pandas-dev/pandas/blob/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/computation/expr.py#L608-L644","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Use a bare column name on the left: df.eval('new_col = col_a + col_b').","For attribute or index assignment, do it outside eval: df.new_col = df['col_a'] + df['col_b']."],"exampleFix":"// before\ndf.eval('df.new_col = col_a + col_b')\n\n// after\ndf.eval('new_col = col_a + col_b')","handlingStrategy":"validation","validationCode":"import ast\ndef lhs_is_simple_name(expr: str) -> bool:\n    try:\n        tree = ast.parse(expr, mode='exec')\n    except SyntaxError:\n        return True  # let eval raise its own error\n    for node in tree.body:\n        if isinstance(node, ast.Assign):\n            for t in node.targets:\n                if not isinstance(t, ast.Name):\n                    return False\n    return True\nif not lhs_is_simple_name(expr):\n    raise ValueError('Assignment lhs must be a bare column name')\ndf.eval(expr)","typeGuard":null,"tryCatchPattern":"try:\n    df.eval(expr)\nexcept SyntaxError as e:\n    if 'single name' in str(e):\n        # do assignment outside eval\n        ...","preventionTips":["Use bare column names on the left of '='.","Perform attribute/index assignment outside eval.","Keep lhs simple: 'new_col = ...'."],"tags":["pandas","eval","assignment","syntax-error","lhs"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}