pandas-dev/pandas · error · ValueError
Of the four parameters: start, end, periods, and freq…
Error message
Of the four parameters: start, end, periods, and freq, exactly three must be specified
What it means
Raised by DatetimeArray._generate_range when com.count_not_none(start, end, periods, freq) != 3. The generator requires exactly three of the four parameters so the fourth is unambiguously inferred; providing two, all four, or only one is rejected. Note this fires after the 'freq missing' guard, so freq is already non-None when reached.
Solutions
- Provide exactly three: start+end+freq, start+end+periods, start+periods+freq, or end+periods+freq.
- If you have start and end only, omit one of periods/freq intentionally and pass the other.
- Use com.count_not_none(start,end,periods,freq)==3 as an upstream assert.
Example fix
// before
pd.date_range('2020-01-01', '2020-01-10') # ValueError: exactly three must be specified
// after
pd.date_range('2020-01-01', '2020-01-10', freq='D') # periods inferred Defensive patterns
Strategy: validation
Validate before calling
def safe_date_range(start=None, end=None, periods=None, freq=None):
n = sum(x is not None for x in [start, end, periods, freq])
if n != 3:
raise ValueError(f"Need exactly 3 of start/end/periods/freq, got {n}")
return pd.date_range(start=start, end=end, periods=periods, freq=freq) Type guard
def exactly_three_of_four(start, end, periods, freq) -> bool:
return sum(x is not None for x in [start, end, periods, freq]) == 3 Try / catch
try:
rng = pd.date_range(start=start, end=end, periods=periods, freq=freq)
except ValueError as e:
if "exactly three must be specified" in str(e):
# drop one arg or supply the missing one intentionally
rng = pd.date_range(start=start, end=end, freq="D")
else:
raise Prevention
- Use pd.core.common.count_not_none(...) in an upstream assert.
- Keep date_range call sites explicit about which three args are set.
- Avoid defaulting multiple of these args to None simultaneously.
When it happens
Trigger: pd.date_range(start, end) with neither periods nor freq (only two of four); pd.date_range(start, end, periods, freq) supplying all four; pd.date_range(start, freq) with two None.
Common situations: Over-specifying after a refactor (adding periods while keeping freq); under-specifying when freq defaults to None; conditional logic that sometimes leaves two args set.
Related errors
- Must provide freq argument if no data is supplied
- Neither `start` nor `end` can be NaT
- periods must be an integer, got
- 'unit' must be one of 's', 'ms', 'us', 'ns'
- cannot assign without a target object
AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11).
Data as JSON: /api/errors/06a36309b8c68fdb.
Report an issue: GitHub.
Appendix: 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 3b7651241d)