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
- Leave exactly one of the four unset (the one you want computed): start+end+freq -> periods; start+periods+freq -> end; end+periods+freq -> start.
- If you supplied all four by mistake, drop the redundant one.
- 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
- Decide which one of the four to derive and leave it unset by design.
- Add a unit test asserting your date_range calls pass exactly three.
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
- periods must be an integer, got {periods}
- Must provide freq argument if no data is supplied
- Neither `start` nor `end` can be NaT
- Inferred frequency {inferred} from passed values does not co
- Passed data is timezone-aware, incompatible with 'tz=None'.
AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07).
Data as JSON: /api/errors/06a36309b8c68fdb.
Report an issue: GitHub.