pandas-dev/pandas · error · ValueError

'value' should be a Timestamp.

Error message

'value' should be a Timestamp.

What it means

Raised by DatetimeArray._unbox_scalar when a value being placed/compared into the array is neither a Timestamp, nor NaT, nor an instance of the array's scalar_type. The array can only hold pandas Timestamps (or NaT) so any other type is rejected at the boundary instead of being coerced into a wrong unit.

Source

Thrown at pandas/core/arrays/datetimes.py:554

                if len(i8values)
                else 0
            )
            if not left_inclusive or not right_inclusive:
                if not left_inclusive and len(i8values) and i8values[0] == start_i8:
                    i8values = i8values[1:]
                if not right_inclusive and len(i8values) and i8values[-1] == end_i8:
                    i8values = i8values[:-1]

        dt64_values = i8values.view(f"datetime64[{unit}]")
        dtype = tz_to_dtype(tz, unit=unit)
        return cls._simple_new(dt64_values, dtype=dtype)

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

    def _unbox_scalar(self, value) -> np.datetime64:
        if not isinstance(value, self._scalar_type) and value is not NaT:
            raise ValueError("'value' should be a Timestamp.")
        self._check_compatible_with(value)
        if value is NaT:
            return np.datetime64(value._value, self.unit)
        else:
            return value.as_unit(self.unit, round_ok=False).asm8

    def _scalar_from_string(self, value) -> Timestamp | NaTType:
        return Timestamp(value, tz=self.tz)

    def _check_compatible_with(self, other) -> None:
        if other is NaT:
            return
        self._assert_tzawareness_compat(other)

    # -----------------------------------------------------------------
    # Descriptive Properties

    def _box_func(self, x: np.datetime64) -> Timestamp | NaTType:

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Wrap the value in pd.Timestamp(...) before assignment.
  2. Parse strings/ints via pd.to_datetime first so they become Timestamps.
  3. For .date() inputs, convert with pd.Timestamp(date).

Example fix

# before
dta = pd.DatetimeIndex(['2020-01-01']).array
dta[0] = datetime.date(2020, 1, 2)

# after
dta[0] = pd.Timestamp(datetime.date(2020, 1, 2))
Defensive patterns

Strategy: type-guard

Validate before calling

if not isinstance(value, (pd.Timestamp, type(pd.NaT))):
    value = pd.Timestamp(value)

Type guard

def is_assignable_to_dta(v) -> bool:
    return isinstance(v, pd.Timestamp) or v is pd.NaT

Try / catch

try:
    dta[0] = value
except (TypeError, ValueError) as e:
    if 'should be a Timestamp' in str(e):
        dta[0] = pd.Timestamp(value)
    else: raise

Prevention

When it happens

Trigger: Assigning a python datetime.date, datetime.time, a numpy.datetime64 of a mismatched unit, a string that wasn't parsed, or a raw int into a DatetimeArray; calling internal .insert/setitem with a non-Timestamp. e.g. dta[0] = datetime.date(2020,1,1) on a tz-aware array in some code paths.

Common situations: Mixing datetime.date and datetime.datetime objects; passing epoch ints thinking they'd be interpreted; cross-library objects (numpy datetime64) of a different resolution than the array.

Related errors


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