pandas-dev/pandas · error · TypeError

unary '-' not supported for dtype '{self.dtype}'

Error message

unary '-' not supported for dtype '{self.dtype}'

What it means

Raised by ArrowExtensionArray.__neg__ (- operator) when pc.negate_checked raises ArrowNotImplementedError — i.e. the dtype has no negation (strings, bool, temporal types without negate, unsigned integers can also overflow). pandas re-raises as TypeError with a clear message naming the dtype, instead of leaking pyarrow's exception. Other dtypes (signed int, float) negate normally.

Source

Thrown at pandas/core/arrays/arrow/array.py:1048

        return self.to_numpy(dtype=dtype, copy=copy)

    def __invert__(self) -> Self:
        # This is a bit wise op for integer types
        if pa.types.is_integer(self._pa_array.type):
            return self._from_pyarrow_array(pc.bit_wise_not(self._pa_array))
        elif pa.types.is_string(self._pa_array.type) or pa.types.is_large_string(
            self._pa_array.type
        ):
            # Raise TypeError instead of pa.ArrowNotImplementedError
            raise TypeError("__invert__ is not supported for string dtypes")
        else:
            return self._from_pyarrow_array(pc.invert(self._pa_array))

    def __neg__(self) -> Self:
        try:
            return self._from_pyarrow_array(pc.negate_checked(self._pa_array))
        except pa.ArrowNotImplementedError as err:
            raise TypeError(
                f"unary '-' not supported for dtype '{self.dtype}'"
            ) from err

    def __pos__(self) -> Self:
        return self._from_pyarrow_array(self._pa_array)

    def __abs__(self) -> Self:
        return self._from_pyarrow_array(pc.abs_checked(self._pa_array))

    # GH 42600: __getstate__/__setstate__ not necessary once
    # https://issues.apache.org/jira/browse/ARROW-10739 is addressed
    def __getstate__(self):
        state = self.__dict__.copy()
        state["_pa_array"] = self._pa_array.combine_chunks()
        # cached properties can be recomputed; don't bloat the pickle
        state["_cache"] = {}
        return state

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Skip non-numeric dtypes: if s.dtype.kind in 'iuf': -s.
  2. Cast to a negate-able type first: -s.astype('int64[pyarrow]').
  3. Use logical not (~) for boolean arrays instead of arithmetic negation.
  4. Filter columns by dtype before applying vectorized negation.

Example fix

# before
out = -df.select_dtypes('number')  # fails if bool[pyarrow] included
# after
numeric = df.select_dtypes(['int64[pyarrow]','float64[pyarrow]','int64','float64'])
out = -numeric
Defensive patterns

Strategy: type-guard

Validate before calling

import pyarrow as pa
from pandas.core.arrays.arrow import ArrowExtensionArray

def negate_if_supported(arr):
    if isinstance(arr, ArrowExtensionArray):
        t = arr._pa_array.type
        if not (pa.types.is_integer(t) or pa.types.is_floating(t) or pa.types.is_decimal(t)):
            raise TypeError(f'cannot negate dtype {arr.dtype}')
    return -arr

out = negate_if_supported(col)

Type guard

import pyarrow as pa
from pandas.core.arrays.arrow import ArrowExtensionArray

def is_negatable_arrow_array(arr) -> bool:
    if not isinstance(arr, ArrowExtensionArray):
        return True
    t = arr._pa_array.type
    return pa.types.is_integer(t) or pa.types.is_floating(t) or pa.types.is_decimal(t)

Try / catch

try:
    out = -col
except TypeError as e:
    if 'unary' in str(e):
        # skip non-numeric, or cast
        out = col  # or col.astype('float64[pyarrow]') then negate
    else:
        raise

Prevention

When it happens

Trigger: `-s` on a pyarrow-backed string/bool/timestamp/bool array: `-pd.Series(['a'], dtype='string[pyarrow]')`, `-pd.Series([True,False], dtype='bool[pyarrow]')`. Also unsigned int overflow if the value can't be negated.

Common situations: Generic arithmetic pipelines applying unary minus to all numeric-looking columns; mixing dtypes after convert_dtypes(dtype_backend='pyarrow') turning a former int column into bool. Migration from numpy-backed where bool negation raised differently.

Related errors


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