pandas-dev/pandas · error · TypeError

value should be a '{self._scalar_type.__name__}' or 'NaT'. G

Error message

value should be a '{self._scalar_type.__name__}' or 'NaT'. Got {msg_got} instead.

What it means

Raised by DatetimeLikeArrayMixin._validate_scalar when a string value cannot be parsed as the expected scalar type (Timestamp for datetime, Timedelta for timedelta, Period for period). The scalar setter tries _scalar_from_string and on ValueError builds this TypeError via _validation_error_message. It is the allow_listlike=False (scalar-only) path.

Source

Thrown at pandas/core/arrays/datetimelike.py:558

            listlike inputs are allowed.
        unbox : bool, default True
            Whether to unbox the result before returning.  Note: unbox=False
            skips the setitem compatibility check.

        Returns
        -------
        self._scalar_type or NaT
        """
        if isinstance(value, self._scalar_type):
            pass

        elif isinstance(value, str):
            # NB: Careful about tzawareness
            try:
                value = self._scalar_from_string(value)
            except ValueError as err:
                msg = self._validation_error_message(value, allow_listlike)
                raise TypeError(msg) from err

        elif is_valid_na_for_dtype(value, self.dtype):
            # GH#18295
            value = NaT

        elif isna(value):
            # if we are dt64tz and value is dt64("NaT"), dont cast to NaT,
            #  or else we'll fail to raise in _unbox_scalar
            msg = self._validation_error_message(value, allow_listlike)
            raise TypeError(msg)

        elif isinstance(value, self._recognized_scalars):
            # error: Argument 1 to "Timestamp" has incompatible type "object"; expected
            # "integer[Any] | float | str | date | datetime | datetime64"
            value = self._scalar_type(value)  # type: ignore[arg-type]

        else:
            msg = self._validation_error_message(value, allow_listlike)

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Pre-parse with pd.to_datetime(...) / pd.to_timedelta(...) so only valid scalars reach the setter.
  2. Validate the string format before assignment (regex or try/except around Timestamp()).
  3. Use NaT for missing values instead of placeholder strings.

Example fix

// before
arr = pd.date_range('2020', periods=3)._data
arr[0] = 'not-a-date'  # TypeError: value should be a 'Timestamp' or 'NaT'

// after
arr[0] = pd.Timestamp('2020-01-01')
Defensive patterns

Strategy: validation

Validate before calling

import pandas as pd
def parse_scalar_for(arr, value):
    try:
        return arr._scalar_from_string(value)
    except ValueError:
        return pd.NaT

Type guard

import pandas as pd
from typing import Any

def is_valid_datetime_string(s: Any) -> bool:
    try:
        pd.Timestamp(s)
        return True
    except (ValueError, TypeError):
        return False

Try / catch

try:
    arr[0] = s
except TypeError as e:
    if 'value should be a' in str(e) and 'NaT' in str(e):
        import pandas as pd
        arr[0] = pd.Timestamp(s) if s else pd.NaT
    else:
        raise

Prevention

When it happens

Trigger: Setting a datetime/timedelta/period array element to a malformed string like 'not-a-date', '2020-13-99', or 'abc'; or to a string with the wrong unit/frequency for the dtype.

Common situations: User-supplied date strings with mixed formats, locale-specific date formats that pandas cannot infer, or strings that look like timestamps but belong to a different scalar domain (e.g. '3 days' set into a datetime array).

Related errors


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