pandas-dev/pandas · error · ValueError

cannot diff {type(arr).__name__} on axis={axis}

Error message

cannot diff {type(arr).__name__} on axis={axis}

What it means

Raised by pandas.core.algorithms.diff when differencing an ExtensionArray that does support differencing (it defines the subtraction operator) but the requested axis is out of range (axis >= arr.ndim). For a 1-D ExtensionArray only axis 0 is valid.

Source

Thrown at pandas/core/algorithms.py:1541

    na = np.nan
    dtype = arr.dtype

    is_bool = is_bool_dtype(dtype)
    if is_bool:
        op = operator.xor
    else:
        op = operator.sub

    if isinstance(dtype, NumpyEADtype):
        # NumpyExtensionArray cannot necessarily hold shifted versions of itself.
        arr = arr.to_numpy()
        dtype = arr.dtype

    if not isinstance(arr, np.ndarray):
        # i.e ExtensionArray
        if hasattr(arr, f"__{op.__name__}__"):
            if axis >= arr.ndim:
                raise ValueError(f"cannot diff {type(arr).__name__} on axis={axis}")
            return op(arr, arr.shift(n))
        else:
            raise TypeError(
                f"{type(arr).__name__} has no 'diff' method. "
                "Convert to a suitable dtype prior to calling 'diff'."
            )

    is_timedelta = False
    if arr.dtype.kind in "mM":
        dtype = np.int64
        arr = arr.view("i8")
        na = iNaT
        is_timedelta = True

    elif is_bool:
        # We have to cast in order to be able to hold np.nan
        dtype = np.object_

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Use axis=0 for 1-D ExtensionArrays.
  2. Perform the diff at the DataFrame level (df.diff(axis=1)) rather than on a single ExtensionArray column.
  3. Check arr.ndim before choosing the axis.

Example fix

# before
arr = pd.array([1, 2, 3], dtype='Int64')
pd.core.algorithms.diff(arr, 1, axis=1)
# after
pd.core.algorithms.diff(arr, 1, axis=0)
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np

def safe_diff_arr(arr, n, axis=0):
    if axis >= np.asarray(arr).ndim:
        raise ValueError(f'axis {axis} invalid for ndim {np.asarray(arr).ndim}')
    return pd.core.algorithms.diff(arr, n, axis=axis)

Type guard

def axis_in_range(arr, axis) -> bool:
    return 0 <= axis < getattr(arr, 'ndim', 1)

Prevention

When it happens

Trigger: Calling diff on a 1-D ExtensionArray (e.g. a nullable/integer or pyarrow-backed array) with axis=1; forwarding a DataFrame axis=1 down to a per-column ExtensionArray diff.

Common situations: Generic code that passes axis through to diff without checking the array's ndim; switching a column's dtype to an ExtensionArray (nullable Int64, ArrowDtype) and reusing axis=1 logic.

Related errors


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