pandas-dev/pandas · error · ValueError

Cannot operate inplace if there is no assignment

Error message

Cannot operate inplace if there is no assignment

What it means

inplace=True tells pandas to mutate the target rather than return a copy. With no assignment in the expression (parsed_expr.assigner is None at eval.py:402), there is nothing to mutate, so inplace is meaningless and pandas refuses rather than silently no-op. The check sits in the assigner-is-None branch alongside the multi-line check.

Source

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

                "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:
                        target = target.copy()
                except AttributeError as err:
                    raise ValueError("Cannot return a copy of the target") from err
            else:
                target = env.target

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Drop inplace=True for read-only expressions and use the returned Series/frame.
  2. Add an assignment to make the expression mutative: df.eval('c = a + b', inplace=True).
  3. Use df.loc or direct column assignment if you want to store the result.

Example fix

// before
df.eval('a + b', inplace=True)
// after
df.eval('c = a + b', inplace=True)
Defensive patterns

Strategy: validation

Validate before calling

def validate_inplace_has_assignment(expr: str, inplace: bool) -> None:
    import ast
    if inplace:
        tree = ast.parse(expr, mode='exec')
        if not any(isinstance(n, ast.Assign) for n in tree.body):
            raise ValueError(
                'inplace=True requires an assignment in the expression'
            )

validate_inplace_has_assignment(expr, inplace)

Type guard

import ast

def inplace_is_safe(expr: str, inplace: bool) -> bool:
    if not inplace:
        return True
    return any(
        isinstance(n, ast.Assign) for n in ast.parse(expr, mode='exec').body
    )

Try / catch

try:
    df.eval(expr, inplace=True)
except ValueError as e:
    if 'no assignment' in str(e):
        result = df.eval(expr, inplace=False)  # fall back to returning
    else:
        raise

Prevention

When it happens

Trigger: df.eval('a + b', inplace=True), df.query('a > b', inplace=True) — any read-only expression combined with inplace=True.

Common situations: Setting inplace=True globally by habit or copy-paste. Confusing query (which filters rows) with assignment semantics. Expecting inplace to mean 'cache the result'.

Related errors


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