pandas-dev/pandas · error · ValueError

'value' should be a Timedelta.

Error message

'value' should be a Timedelta.

What it means

Raised by TimedeltaArray._unbox_scalar when the value is neither an instance of self._scalar_type (Timedelta) nor the NaT sentinel. TimedeltaArray only accepts Timedelta scalars (or NaT) for operations like item()/insert; passing a datetime, int, float, or str forces the caller to convert explicitly via pd.Timedelta(...). This prevents silent unit misinterpretation (e.g. treating a raw int as nanoseconds vs seconds).

Source

Thrown at pandas/core/arrays/timedeltas.py:327

        if freq is not None:
            index = generate_regular_range(start, end, periods, freq, unit=unit)
        else:
            index = np.linspace(start._value, end._value, periods).astype("i8")

        if not left_closed:
            index = index[1:]
        if not right_closed:
            index = index[:-1]

        td64values = index.view(f"m8[{unit}]")
        return cls._simple_new(td64values, dtype=td64values.dtype)

    # ----------------------------------------------------------------
    # DatetimeLike Interface

    def _unbox_scalar(self, value) -> np.timedelta64:
        if not isinstance(value, self._scalar_type) and value is not NaT:
            raise ValueError("'value' should be a Timedelta.")
        self._check_compatible_with(value)
        if value is NaT:
            return np.timedelta64(value._value, self.unit)
        else:
            #  error: Incompatible return value type (got "timedelta64[timedelta |
            # int | None] | datetime64[date | int | None]",
            # expected "timedelta64[timedelta | int | None]")
            return value.as_unit(self.unit, round_ok=False).asm8  # type: ignore[return-value]

    def _scalar_from_string(self, value) -> Timedelta | NaTType:
        return Timedelta(value)

    def _check_compatible_with(self, other) -> None:
        # we don't have anything to validate.
        pass

    # ----------------------------------------------------------------
    # Array-Like / EA-Interface Methods

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Wrap the value in pd.Timedelta: `td_arr[i] = pd.Timedelta(value, unit='s')`.
  2. Use pd.NaT for missing rather than None or 0.
  3. If passing ints with known units, convert via pd.to_timedelta(value, unit=...).

Example fix

# before
arr[0] = 60  # ValueError, ambiguous units
# after
arr[0] = pd.Timedelta(60, unit='s')
Defensive patterns

Strategy: type-guard

Validate before calling

import pandas as pd
from pandas._libs.tslibs import NaT, Timedelta

def unbox_td_scalar(arr, value):
    if value is NaT:
        return value
    if not isinstance(value, Timedelta):
        value = pd.Timedelta(value)
    return value

Type guard

from pandas._libs.tslibs import Timedelta, NaT
def is_td_or_nat(value) -> bool:
    return isinstance(value, Timedelta) or value is NaT

Try / catch

try:
    arr[i] = value
except ValueError as e:
    if 'should be a Timedelta' in str(e):
        arr[i] = pd.Timedelta(value)
    else:
        raise

Prevention

When it happens

Trigger: Calling `td_arr[0] = 5`, `td_arr.item() = datetime.now()`, or any scalar-setting path with a non-Timedelta. The check at timedeltas.py:326 is `not isinstance(value, self._scalar_type) and value is not NaT`.

Common situations: Assigning raw integers/floats assuming nanosecond semantics; passing datetime where timedelta was expected; mixing py objects into a typed array.

Related errors


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