pandas-dev/pandas · error · ValueError
'value' should be a Period. Got
Error message
'value' should be a Period. Got '{value}' instead. What it means
Raised by PeriodArray._unbox_scalar when the supplied value is neither NaT nor an instance of self._scalar_type (i.e. pd.Period). _unbox_scalar converts a scalar to its int64 ordinal for internal ops; only Period (matching freq) and NaT are valid inputs. Anything else (int, str, Timestamp, datetime) is rejected with the offending value shown.
Solutions
- Convert the scalar to a Period first: pd.Period(value, freq=idx.freq).
- Use NaT for missing-value slots instead of None/NaN.
- For lookups, rely on the public Index methods which perform conversion; avoid calling _unbox_scalar directly.
Example fix
# before
idx = pd.period_range('2023', periods=3, freq='M')
idx._unbox_scalar('2023-01') # raises
# after
idx._unbox_scalar(pd.Period('2023-01', freq='M')) Defensive patterns
Strategy: type-guard
Validate before calling
import pandas as pd
def unbox_for_period(period_array, value):
if value is pd.NaT:
return period_array._unbox_scalar(pd.NaT)
if not isinstance(value, pd.Period):
value = pd.Period(value, freq=period_array.freq)
return period_array._unbox_scalar(value) 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:
idx._unbox_scalar(value)
except ValueError as e:
if 'should be a Period' in str(e):
idx._unbox_scalar(pd.Period(value, freq=idx.freq))
else:
raise Prevention
- Convert lookups to pd.Period(value, freq=idx.freq) before passing to period index internals.
- Use pd.NaT (not None/np.nan) for missing period scalars.
- Avoid calling _unbox_scalar directly; prefer public Index lookup methods.
When it happens
Trigger: Internal call from searchsorted/take/fillna with a non-Period scalar. PeriodIndex.get_loc('2023-01-01') where the string isn't converted to a Period first. Passing an int ordinal where a Period is expected.
Common situations: Mixing PeriodIndex with raw strings/Timestamps in lookups; assuming the index will coerce the scalar; downstream code that passes ordinals directly into Period-aware ops.
Related errors
- dtype must be PeriodDtype
- Mismatched Period array lengths
- Not enough parameters to construct Period range
- Of the three parameters: start, end, and periods, exactly…
- Quarter must be 1 <= q <= 4
AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11).
Data as JSON: /api/errors/c5e3852556ca83d9.
Report an issue: GitHub.
Appendix: source
Thrown at pandas/core/arrays/period.py:398
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 noView on GitHub (pinned to 3b7651241d)