pandas-dev/pandas · error · ValueError

'value' should be a Period. Got '{value}' instead.

Error message

'value' should be a Period. Got '{value}' instead.

What it means

Raised by PeriodArray._unbox_scalar when the value is neither NaT nor a Period instance. _unbox_scalar converts a scalar into the int64 ordinal storage; only Period (and NaT) carry the frequency context required, so any other scalar (Timestamp, str, int) is rejected.

Source

Thrown at pandas/core/arrays/period.py:388

        return cls._simple_new(subarr, dtype=dtype)

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

    def _unbox_scalar(
        self,
        # error: Argument 1 of "_unbox_scalar" is incompatible with supertype
        # "pandas.core.arrays.datetimelike.DatetimeLikeArrayMixin"; supertype
        #  defines the argument type as "Period | Timestamp | Timedelta | NaTType"
        value: Period | NaTType,  # type: ignore[override]
    ) -> np.int64:
        if value is NaT:
            return np.int64(value._value)
        elif isinstance(value, self._scalar_type):
            self._check_compatible_with(value)
            return np.int64(value.ordinal)
        else:
            raise ValueError(f"'value' should be a Period. Got '{value}' instead.")

    def _scalar_from_string(self, value: str) -> Period:
        return Period(value, freq=self.freq)

    def _check_compatible_with(
        self,
        #  error: Argument 1 of "_check_compatible_with" is incompatible with
        # supertype "pandas.core.arrays.datetimelike.DatetimeLikeArrayMixin";
        # supertype defines the argument type as "Period | Timestamp | Timedelta
        # | NaTType"
        other: Period | NaTType | PeriodArray,  # type: ignore[override]
    ) -> None:
        if other is NaT:
            return
        elif isinstance(other, Period):
            self._require_matching_unit(other._dtype._freqstr)
        else:
            # error: Item "NaTType" of "NaTType | PeriodArray" has no

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Wrap the scalar: pa[i] = pd.Period('2020-01-01', freq=pa.freq).
  2. Use NaT for missing values: pa[i] = pd.NaT.
  3. Match the Period's freq to the array's freq to avoid downstream IncompatibleFrequency.

Example fix

# before
pa = pd.period_array(['2020-01-01','2020-01-02'], dtype=pd.PeriodDtype('D'))
pa[0] = '2021-01-01'
# after
pa[0] = pd.Period('2021-01-01', freq='D')
Defensive patterns

Strategy: type-guard

Validate before calling

import pandas as pd

def to_period_scalar(value, freq):
    if value is pd.NaT or isinstance(value, pd.Period):
        return value
    return pd.Period(value, freq=freq)

Type guard

import pandas as pd

def is_period_or_nat(value) -> bool:
    return value is pd.NaT or isinstance(value, pd.Period)

Try / catch

try:
    pa[i] = value
except ValueError:
    pa[i] = pd.Period(value, freq=pa.freq)

Prevention

When it happens

Trigger: Assignment/searchset operations that route a scalar through _unbox_scalar: pa[0] = '2020-01-01', pa.searchsorted(some_timestamp), fillna with a non-Period value on a period Series.

Common situations: Trying to assign a string or Timestamp into a period array. fillna with a Python int instead of pd.Period. Cross-dtype operations mixing period and datetime scalars.

Related errors


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