{"record":{"id":"00e8e0c97a1ac75a","repo":"pandas-dev/pandas","slug":"multi-line-expressions-are-only-valid-in-the-conte","errorCode":null,"errorMessage":"multi-line expressions are only valid in the context of data, use DataFrame.eval","messagePattern":"multi-line expressions are only valid in the context of data, use DataFrame\\.eval","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"pandas/core/computation/eval.py","lineNumber":349,"sourceCode":"    1    pig   20          40\n    \"\"\"\n    inplace = validate_bool_kwarg(inplace, \"inplace\")\n\n    exprs: list[str | BinOp]\n    if isinstance(expr, str):\n        _check_expression(expr)\n        exprs = [e.strip() for e in expr.splitlines() if e.strip() != \"\"]\n    elif isinstance(expr, NDFrame):\n        # GH#16289 a Series/DataFrame would otherwise be converted to its\n        #  (possibly truncated) repr and parsed, producing a confusing error\n        raise ValueError(f\"expr must be a string to be evaluated, {type(expr)} given\")\n    else:\n        # ops.BinOp; for internal compat, not intended to be passed by users\n        exprs = [expr]\n    multi_line = len(exprs) > 1\n\n    if multi_line and target is None:\n        raise ValueError(\n            \"multi-line expressions are only valid in the \"\n            \"context of data, use DataFrame.eval\"\n        )\n    engine = _check_engine(engine)\n    _check_parser(parser)\n    _check_resolvers(resolvers)\n\n    ret = None\n    first_expr = True\n    target_modified = False\n\n    for expr in exprs:\n        expr = _convert_expression(expr)\n        _check_for_locals(expr, level, parser)\n\n        # get our (possibly passed-in) scope\n        env = ensure_scope(\n            level + 1,","sourceCodeStart":331,"sourceCodeEnd":367,"githubUrl":"https://github.com/pandas-dev/pandas/blob/71959b8cb9b2459c16e14b34f28b178ccfe14735/pandas/core/computation/eval.py#L331-L367","documentation":"Multi-line expressions (splitlines yielding more than one non-empty line) only make sense when each line can assign into a target object. The top-level pd.eval default target is None, so there is nowhere to write the assignments; pandas tells you to use DataFrame.eval, which supplies the frame as the target. The check fires at eval.py:348 before any parsing happens.","triggerScenarios":"pd.eval('a = b + 1\\nc = a * 2') with no target kwarg. Passing a multi-line string to pd.eval expecting column assignments to materialize somewhere.","commonSituations":"Copying a multi-line DataFrame.eval recipe into a pd.eval call. Building a chain of column computations as one string and routing it through the wrong entry point.","solutions":["Switch to df.eval('a = b + 1\\nc = a * 2') so the DataFrame is the assignment target.","Pass target=df explicitly: pd.eval(multiline_expr, target=df).","Split the multi-line string into separate single-line pd.eval calls."],"exampleFix":"// before\npd.eval('a = b + 1\\nc = a * 2')\n// after\ndf.eval('a = b + 1\\nc = a * 2')","handlingStrategy":"validation","validationCode":"def route_multiline(expr: str, target):\n    lines = [ln for ln in expr.splitlines() if ln.strip()]\n    if len(lines) > 1 and target is None:\n        raise ValueError(\n            'Multi-line expression needs a target; use df.eval(...) instead'\n        )\n\n# at call site:\nif isinstance(target_or_df, pd.DataFrame):\n    target_or_df.eval(multiline_expr)\nelse:\n    route_multiline(multiline_expr, target_or_df)","typeGuard":"def needs_target_for_multiline(expr: str, target) -> bool:\n    return len([l for l in expr.splitlines() if l.strip()]) > 1 and target is None","tryCatchPattern":"try:\n    pd.eval(expr)\nexcept ValueError as e:\n    if 'multi-line' in str(e) and target is None:\n        df.eval(expr)  # if a df is in scope\n    else:\n        raise","preventionTips":["Use DataFrame.eval for any string containing newlines.","When building expression strings dynamically, prefer single-line pd.eval calls.","Document helper functions to make clear whether they expect single- or multi-line input."],"tags":["pandas","eval","multi-line","target","assignment"],"analyzedSha":"71959b8cb9b2459c16e14b34f28b178ccfe14735","analyzedAt":"2026-08-07T01:30:20.476Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}