pandas-dev/pandas · error · ValueError

Of the four parameters: start, end, periods, and freq, exact

Error message

Of the four parameters: start, end, periods, and freq, exactly three must be specified

What it means

Raised in _generate_range when the count of non-None values among start, end, periods, freq is not exactly three. With all four, the system is over-determined and the constraints may contradict; with fewer than three it is under-determined. Exactly one of start/end/periods is the unknown to solve for.

Source

Thrown at pandas/core/arrays/datetimes.py:409

        cls,
        start,
        end,
        periods: int | None,
        freq,
        tz=None,
        normalize: bool = False,
        ambiguous: TimeAmbiguous = "raise",
        nonexistent: TimeNonexistent = "raise",
        inclusive: IntervalClosedType = "both",
        *,
        unit: TimeUnit = "ns",
    ) -> Self:
        periods = dtl.validate_periods(periods)
        if freq is None and any(x is None for x in [periods, start, end]):
            raise ValueError("Must provide freq argument if no data is supplied")

        if com.count_not_none(start, end, periods, freq) != 3:
            raise ValueError(
                "Of the four parameters: start, end, periods, "
                "and freq, exactly three must be specified"
            )
        freq = to_offset(freq)

        if start is not None:
            start = Timestamp(start)

        if end is not None:
            end = Timestamp(end)

        if start is NaT or end is NaT:
            raise ValueError("Neither `start` nor `end` can be NaT")

        if unit is not None:
            if unit not in ["s", "ms", "us", "ns"]:
                raise ValueError("'unit' must be one of 's', 'ms', 'us', 'ns'")
        else:

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Leave exactly one of the four unset (the one you want computed): start+end+freq -> periods; start+periods+freq -> end; end+periods+freq -> start.
  2. If you supplied all four by mistake, drop the redundant one.
  3. For a single timestamp, use pd.Timestamp or pd.DatetimeIndex([start]) rather than date_range.

Example fix

# before (over-specified)
pd.date_range('2020-01-01', '2020-01-05', periods=5, freq='D')

# after (let pandas derive periods)
pd.date_range('2020-01-01', '2020-01-05', freq='D')
Defensive patterns

Strategy: validation

Validate before calling

provided = sum(x is not None for x in (start, end, periods, freq))
if provided != 3:
    raise ValueError(f'exactly 3 of start/end/periods/freq required, got {provided}')

Try / catch

try:
    pd.date_range(start, end, periods, freq)
except ValueError as e:
    if 'exactly three must be specified' in str(e):
        # drop the over-specified or under-specified param
        pd.date_range(start, end, freq='D')
    else: raise

Prevention

When it happens

Trigger: pd.date_range(start, end, periods, freq) all four set; pd.date_range(start, end) with neither periods nor freq (only two); pd.date_range(start) with only start.

Common situations: Passing all four 'just to be safe'. Migrating from an older call that inferred the missing one. Defaults of None on periods/freq interacting with provided start/end.

Related errors


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