pandas-dev/pandas · error · ValueError

Cannot return a copy of the target

Error message

Cannot return a copy of the target

What it means

Raised when inplace=False, an assignment exists, and the target object does not support .copy(). When returning a copy (the default for inplace=False), pandas calls target.copy() (or target.copy(deep=False) for NDFrame) so the original is not mutated. If the target is a type without a .copy() method (e.g., an int, a plain list used as a target, or a custom object), the AttributeError is caught and re-raised as this ValueError.

Solutions

  1. Use a DataFrame or dict as the target: pd.eval('x = 1', target={}) or target=df.
  2. Pass inplace=True to avoid the copy step — but only if you intend to mutate the original target in place.
  3. Wrap your target in a type that supports .copy() (e.g., a dict or a custom class with a copy method).

Example fix

// before
pd.eval('x = 1', target=5)

// after
target = {}
pd.eval('x = 1', target=target)  # returns {'x': 1}
Defensive patterns

Strategy: type-guard

Validate before calling

if target is not None and not hasattr(target, 'copy'):
    raise TypeError(f'target {type(target).__name__} must support .copy() when inplace=False')
pd.eval(expr, target=target, inplace=False)

Type guard

def is_copyable_target(t) -> bool:
    return t is None or hasattr(t, 'copy')

Try / catch

try:
    pd.eval(expr, target=target)
except ValueError as e:
    if 'Cannot return a copy' in str(e):
        result = pd.eval(expr, target=target, inplace=True)
    else:
        raise

Prevention

When it happens

Trigger: Calling pd.eval('x = 1', target=5, inplace=False) where target is an int — ints have no .copy(). Or target=some_list where list.copy exists but a different non-copyable object was passed.

Common situations: Using a plain Python object (int, tuple, or a namespace object) as a target for pd.eval assignment instead of a DataFrame, dict, or other copyable container; experimentation with target types.

Related errors


AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11). Data as JSON: /api/errors/709c7baff902ec36. Report an issue: GitHub.

Appendix: source

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

                )
            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

            # TypeError is most commonly raised (e.g. int, list), but you
            # get IndexError if you try to do this assignment on np.ndarray.
            # we will ignore numpy warnings here; e.g. if trying
            # to use a non-numeric indexer
            try:
                if inplace and isinstance(target, NDFrame):
                    target.loc[:, assigner] = ret
                else:
                    target[assigner] = ret  # pyright: ignore[reportIndexIssue]
            except (TypeError, IndexError) as err:
                raise ValueError("Cannot assign expression output to target") from err

            if not resolvers:
                resolvers = ({assigner: ret},)
            else:

View on GitHub (pinned to 3b7651241d)