{"record":{"id":"c21a70eddc9a268a","repo":"pandas-dev/pandas","slug":"can-only-assign-a-single-expression","errorCode":null,"errorMessage":"can only assign a single expression","messagePattern":"can only assign a single expression","errorType":"exception","errorClass":"SyntaxError","httpStatus":null,"severity":"error","filePath":"pandas/core/computation/expr.py","lineNumber":624,"sourceCode":"            upper = self.visit(upper).value\n        step = node.step\n        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","sourceCodeStart":606,"sourceCodeEnd":642,"githubUrl":"https://github.com/pandas-dev/pandas/blob/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/computation/expr.py#L606-L642","documentation":"Raised by visit_Assign() when the assignment node has more than one target (len(node.targets) != 1). pandas eval supports only a single assignment target like 'c = a + b'; chained or multiple-target assignments such as 'a = b = 1' or tuple unpacking 'a, b = 1, 2' are rejected because the assigner model tracks exactly one name.","triggerScenarios":"df.eval('a = b = 1') (chained assignment); df.eval('a, b = 1, 2') (tuple unpacking, though this may hit a different error first); any expression with multiple '=' targets in one statement.","commonSituations":"Trying to initialize multiple columns in one eval line; porting Python multiple-assignment idioms into the eval DSL.","solutions":["Split into one assignment per line: df.eval('a = 1\\nb = 1').","Assign each target in a separate df.eval call or via regular DataFrame column assignment df['a'] = 1; df['b'] = 1."],"exampleFix":"// before\ndf.eval('a = b = 1')\n\n// after\ndf.eval('a = 1\\nb = 1')","handlingStrategy":"validation","validationCode":"import re\ndef is_single_target_assign(expr: str) -> bool:\n    # reject chained 'a = b ='\n    return expr.count('=') == 1\nif not is_single_target_assign(expr):\n    raise ValueError('Use one assignment target per line')\ndf.eval(expr)","typeGuard":null,"tryCatchPattern":"try:\n    df.eval(expr)\nexcept SyntaxError as e:\n    if 'single expression' in str(e):\n        # split chained assignments\n        ...","preventionTips":["One assignment target per eval line.","Use multiple df.eval calls or multi-line for several columns.","Avoid Python chained-assignment idioms in eval."],"tags":["pandas","eval","assignment","syntax-error","multiple-targets"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}