pandas-dev/pandas · error · ValueError

Not enough parameters to construct Period range

Error message

Not enough parameters to construct Period range

What it means

Raised by PeriodArray._generate_range when both `start` and `end` are None. A period range needs at least one anchor (start or end); with neither, plus only `periods`/`freq`, there is no way to fix the actual dates. (Note this is distinct from the start/end/periods count check at _get_ordinal_range.)

Source

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

        PeriodArray[freq]
        """
        if isinstance(freq, BaseOffset):
            freq = PeriodDtype(freq)._freqstr
        data, freq = dt64arr_to_periodarr(data, freq, tz)
        dtype = PeriodDtype(freq)
        return cls(data, dtype=dtype)

    @classmethod
    def _generate_range(cls, start, end, periods, freq):
        periods = dtl.validate_periods(periods)

        if freq is not None:
            freq = Period._maybe_convert_freq(freq)

        if start is not None or end is not None:
            subarr, freq = _get_ordinal_range(start, end, periods, freq)
        else:
            raise ValueError("Not enough parameters to construct Period range")

        return subarr, freq

    @classmethod
    def _from_fields(cls, *, fields: dict, freq) -> Self:
        subarr, freq = _range_from_fields(freq=freq, **fields)
        dtype = PeriodDtype(freq)
        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]

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Provide a start (or end): pd.period_range(start='2020-01-01', periods=N, freq='D').
  2. If you have end, pass it: pd.period_range(end='2020-12-31', periods=N, freq='D').
  3. Validate that at least one of start/end is non-None before calling.

Example fix

# before
pd.period_range(periods=5, freq='D')
# after
pd.period_range(start='2020-01-01', periods=5, freq='D')
Defensive patterns

Strategy: validation

Validate before calling

import pandas as pd

def safe_period_range(start=None, end=None, periods=None, freq=None):
    if start is None and end is None:
        raise ValueError('Either start or end must be provided for a period range')
    return pd.period_range(start=start, end=end, periods=periods, freq=freq)

Type guard

def has_anchor(start, end) -> bool:
    return start is not None or end is not None

Try / catch

try:
    rng = pd.period_range(start=start, end=end, periods=periods, freq=freq)
except ValueError:
    rng = pd.period_range(start='2020-01-01', periods=periods, freq=freq)

Prevention

When it happens

Trigger: Calling period_range/PeriodIndex with periods=N and freq=... but neither start nor end. Internal _generate_range invocations where both anchors were filtered out as None.

Common situations: Building a range dynamically where start/end come from optional config and both end up unset. Refactoring that drops the start argument by mistake.

Related errors


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