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 the value passed to setitem/search/etc. is neither an instance of the array's _scalar_type (Timestamp) nor pd.NaT. Internally pandas unboxes scalars to raw datetime64 to compare/store them; a non-Timestamp object (e.g. a python datetime, a string, an int) cannot be unboxed without ambiguity, so it is rejected at this low level.
Solutions
- Wrap the value: pd.Timestamp(value) before passing.
- Use the public setitem / .get_loc / .get_indexer APIs which coerce for you.
- If you need NaT semantics, pass pd.NaT explicitly rather than None.
Example fix
// before val = datetime.datetime(2020, 1, 1) idx._unbox_scalar(val) # ValueError: 'value' should be a Timestamp. // after val = pd.Timestamp(datetime.datetime(2020, 1, 1)) idx._unbox_scalar(val)
Defensive patterns
Strategy: type-guard
Validate before calling
def unbox_for_dt(idx, value):
if value is not pd.NaT and not isinstance(value, pd.Timestamp):
value = pd.Timestamp(value)
return idx._unbox_scalar(value) Type guard
def is_timestamp_or_nat(value) -> bool:
return value is pd.NaT or isinstance(value, pd.Timestamp) Try / catch
try:
raw = idx._unbox_scalar(value)
except ValueError as e:
if "should be a Timestamp" in str(e):
raw = idx._unbox_scalar(pd.Timestamp(value))
else:
raise Prevention
- Always wrap values with pd.Timestamp before low-level datetime array ops.
- Prefer public setitem/get_loc APIs that coerce automatically.
- Reserve _unbox_scalar for code that has already validated inputs.
When it happens
Trigger: Indexing/setting a DatetimeArray/DatetimeIndex with a python datetime.datetime, a str, or an int directly through the internal _unbox_scalar path (e.g. idx._unbox_scalar(value)); less commonly hit via public setitem when the value bypasses normal coercion.
Common situations: Subclassing/extending DatetimeArray and feeding raw python datetime objects; calling internal methods directly; mixed-type assignment that skips the public coercion layer.
Related errors
- 'value' should be a Timedelta.
- 'value' should be a Period. Got
- Values resolution does not match dtype.
- Cannot assign expression output to target
- Cannot construct from scalar data. Pass a sequence instead.
AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11).
Data as JSON: /api/errors/645df86ecbfb4222.
Report an issue: GitHub.
Appendix: 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 3b7651241d)