{"record":{"id":"48b332abcc28cf19","repo":"pandas-dev/pandas","slug":"cannot-diff-type-arr-name-on-axis-axis","errorCode":null,"errorMessage":"cannot diff {type(arr).__name__} on axis={axis}","messagePattern":"cannot diff (.+?) on axis=(.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"pandas/core/algorithms.py","lineNumber":1541,"sourceCode":"    na = np.nan\n    dtype = arr.dtype\n\n    is_bool = is_bool_dtype(dtype)\n    if is_bool:\n        op = operator.xor\n    else:\n        op = operator.sub\n\n    if isinstance(dtype, NumpyEADtype):\n        # NumpyExtensionArray cannot necessarily hold shifted versions of itself.\n        arr = arr.to_numpy()\n        dtype = arr.dtype\n\n    if not isinstance(arr, np.ndarray):\n        # i.e ExtensionArray\n        if hasattr(arr, f\"__{op.__name__}__\"):\n            if axis >= arr.ndim:\n                raise ValueError(f\"cannot diff {type(arr).__name__} on axis={axis}\")\n            return op(arr, arr.shift(n))\n        else:\n            raise TypeError(\n                f\"{type(arr).__name__} has no 'diff' method. \"\n                \"Convert to a suitable dtype prior to calling 'diff'.\"\n            )\n\n    is_timedelta = False\n    if arr.dtype.kind in \"mM\":\n        dtype = np.int64\n        arr = arr.view(\"i8\")\n        na = iNaT\n        is_timedelta = True\n\n    elif is_bool:\n        # We have to cast in order to be able to hold np.nan\n        dtype = np.object_\n","sourceCodeStart":1523,"sourceCodeEnd":1559,"githubUrl":"https://github.com/pandas-dev/pandas/blob/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/algorithms.py#L1523-L1559","documentation":"When diff() is called on an ExtensionArray (a non-numpy pandas array type like CategoricalArray or IntervalArray), the code checks whether the array supports the subtraction operator. If it does, it verifies that the requested axis is valid for the array's dimensionality. Since ExtensionArrays are 1-D, any axis >= 1 is invalid. This ValueError indicates an attempt to diff along a non-existent axis on a 1-D extension array.","triggerScenarios":"Calling diff(axis=1) on a 1-D ExtensionArray (e.g., a Categorical or Interval column extracted as ._values). Internally passing axis >= arr.ndim when arr is a 1-D extension array. This is more commonly an internal routing error than a direct user mistake.","commonSituations":"DataFrame.diff(axis=1) on a column whose dtype is an ExtensionArray type — the internal code may route the per-column diff call with the wrong axis. Using a third-party ExtensionArray subclass that interacts with diff in unexpected ways.","solutions":["If calling diff on a DataFrame, ensure the axis matches: df.diff(axis=0) operates along rows, df.diff(axis=1) along columns.","Convert the ExtensionArray to numpy first: df['col'].astype(np.float64).diff().","If this is an internal/indirect trigger, check whether your ExtensionArray's __sub__ or __xor__ method is interfering with the axis check."],"exampleFix":"# before — axis=1 on a single extension-array column\n df['interval_col']._values.diff(n=1, axis=1)\n\n# after — convert to numeric or use DataFrame-level diff\ndf[['interval_col']].diff(axis=0)","handlingStrategy":"validation","validationCode":"def safe_diff_extension_array(arr, n=1, axis=0):\n    if axis >= arr.ndim:\n        raise ValueError(f\"axis={axis} is invalid for ndim={arr.ndim}\")\n    return arr.diff(n, axis=axis) if hasattr(arr, 'diff') else None","typeGuard":"def is_valid_diff_axis(arr, axis) -> bool:\n    return axis < np.asarray(arr).ndim","tryCatchPattern":"try:\n    result = df.diff(n=1, axis=axis)\nexcept ValueError as e:\n    if \"cannot diff\" in str(e) and \"axis\" in str(e):\n        result = df.diff(n=1, axis=0)  # fall back to default axis\n    else:\n        raise","preventionTips":["Ensure the axis argument does not exceed the dimensionality of the data.","For 1-D extension arrays, always use axis=0.","Convert extension arrays to numpy for multi-axis operations."],"tags":["pandas","diff","extension-array","axis","valueerror"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}