pandas-dev/pandas · error · ValueError

Multi-line expressions are only valid if all expressions con

Error message

Multi-line expressions are only valid if all expressions contain an assignment

What it means

When a multi-line expression is allowed (target supplied), every sub-expression must be an assignment because the loop in eval.py:361 assigns sequentially and only the final return value is non-None. If any line is a bare expression (parsed_expr.assigner is None at eval.py:402), there is no column to assign and no meaningful return, so pandas raises. This keeps multi-line semantics unambiguous.

Source

Thrown at pandas/core/computation/eval.py:404

                )
            )
        ):
            warnings.warn(
                "Engine has switched to 'python' because numexpr does not support "
                "extension array dtypes. Please set your engine to python manually.",
                RuntimeWarning,
                stacklevel=find_stack_level(),
            )
            engine = "python"

        # construct the engine and evaluate the parsed expression
        eng = ENGINES[engine]
        eng_inst = eng(parsed_expr)
        ret = eng_inst.evaluate()

        if parsed_expr.assigner is None:
            if multi_line:
                raise ValueError(
                    "Multi-line expressions are only valid "
                    "if all expressions contain an assignment"
                )
            if inplace:
                raise ValueError("Cannot operate inplace if there is no assignment")

        # assign if needed
        assigner = parsed_expr.assigner
        if env.target is not None and assigner is not None:
            target_modified = True

            # if returning a copy, copy only on the first assignment
            if not inplace and first_expr:
                try:
                    target = env.target
                    if isinstance(target, NDFrame):
                        target = target.copy(deep=False)
                    else:

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Make every line an assignment, e.g. df.eval('a = b + 1\nc = b + 2').
  2. Move the bare expression into a separate, single-line df.eval/df.query call.
  3. Capture the bare line's result by assigning it to a new column.

Example fix

// before
df.eval('a = b + 1\nb + 2')
// after
df.eval('a = b + 1\nc = b + 2')
Defensive patterns

Strategy: validation

Validate before calling

def validate_multiline_all_assigned(expr: str) -> None:
    import ast
    for line in (l for l in expr.splitlines() if l.strip()):
        tree = ast.parse(line, mode='exec')
        if not any(isinstance(n, ast.Assign) for n in tree.body):
            raise ValueError(
                f'Every multi-line expression must assign; offending line: {line!r}'
            )

validate_multiline_all_assigned(multiline_expr)

Type guard

import ast

def all_lines_assign(expr: str) -> bool:
    return all(
        any(isinstance(n, ast.Assign) for n in ast.parse(l, mode='exec').body)
        for l in (s for s in expr.splitlines() if s.strip())
    )

Try / catch

try:
    df.eval(expr)
except ValueError as e:
    if 'must contain an assignment' in str(e):
        # split assignment lines from any bare expression and handle separately
        ...
    raise

Prevention

When it happens

Trigger: df.eval('a = b + 1\nb + 2') — the second line has no '='. Any multi-line df.eval string where at least one line is a pure expression rather than an assignment.

Common situations: Appending a final 'return' line to a sequence of assignments expecting it to be yielded. Mixing query-style filters with column assignments in one string.

Related errors


AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07). Data as JSON: /api/errors/65f07ed9f466e0f9. Report an issue: GitHub.