pandas-dev/pandas · error · TypeError

unary '-' not supported for dtype

Error message

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

What it means

Raised by ArrowExtensionArray.__neg__ (unary minus) when pc.negate_checked fails with ArrowNotImplementedError, i.e. the dtype does not support negation (strings, booleans, dates without time, binary, nested types). The check is wrapped so that unsupported types surface a clear TypeError instead of pyarrow's lower-level error.

Solutions

  1. Ensure the operand is numeric or duration: check s.dtype.kind in 'iuf' before negating.
  2. Cast to a numeric pyarrow dtype first: s.astype('int64[pyarrow]').
  3. For datetimes/timestamps where you want a duration, use subtraction against an epoch instead of unary minus.
  4. Branch on dtype: if not pa.types.is_signed_integer(...) and not pa.types.is_floating(...) and not pa.types.is_duration(...): skip negation.

Example fix

# before
s = pd.Series(['a', 'b'], dtype="string[pyarrow]")
-s  # raises TypeError: unary '-' not supported for dtype 'string[pyarrow]'

# after
num = pd.Series([1, 2], dtype="int64[pyarrow]")
-num
Defensive patterns

Strategy: type-guard

Validate before calling

import pyarrow as pa

def supports_negate(arr) -> bool:
    t = arr._pa_array.type
    return (pa.types.is_signed_integer(t) or pa.types.is_unsigned_integer(t)
            or pa.types.is_floating(t) or pa.types.is_duration(t))

def safe_neg(arr):
    if not supports_negate(arr):
        raise TypeError(f"unary '-' not supported for dtype {arr.dtype}")
    return -arr

Type guard

import pyarrow as pa

def is_negatable_dtype(arr) -> bool:
    t = arr._pa_array.type
    return any(f(t) for f in (pa.types.is_signed_integer, pa.types.is_floating, pa.types.is_duration))

Try / catch

try:
    result = -arr
except TypeError as e:
    if "unary '-' not supported" in str(e):
        # cast to a compatible numeric dtype if applicable
        result = -arr.astype('int64[pyarrow]')
    else:
        raise

Prevention

When it happens

Trigger: -arr on a string/boolean/binary/date32/date64 ArrowExtensionArray; -s where s is a pyarrow-backed Series whose dtype is not numeric or duration; applying np.negative to such an array.

Common situations: Code that assumes numeric dtype but received string[pyarrow] after inference; date32/date64 columns where unary minus is undefined; boolean pyarrow arrays.

Related errors


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

Appendix: source

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

        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 3b7651241d)