pandas-dev/pandas · error · ValueError

at least 'start' or 'end' should be specified if a 'period'

Error message

at least 'start' or 'end' should be specified if a 'period' is given.

What it means

`ValueError("at least 'start' or 'end' should be specified if a 'period' is given.")` from `generate_regular_range`'s final `else` branch. It fires when none of the supported parameter combinations are met: (periods None + start + end), (start + periods), or (end + periods). In practice the message points at the most common cause — `periods` given without either `start` or `end` — though the branch also catches 'periods=None but only one of start/end' and 'all None'.

Source

Thrown at pandas/core/arrays/_ranges.py:92

        raise ValueError(
            f"freq={freq} is incompatible with unit={unit}. "
            "Use a lower freq or a higher unit instead."
        ) from err
    stride = int(td._value)

    if periods is None and istart is not None and iend is not None:
        b = istart
        # cannot just use e = Timestamp(end) + 1 because arange breaks when
        # stride is too large, see GH10887
        e = b + (iend - b) // stride * stride + stride // 2 + 1
    elif istart is not None and periods is not None:
        b = istart
        e = _generate_range_overflow_safe(b, periods, stride, side="start")
    elif iend is not None and periods is not None:
        e = iend + stride
        b = _generate_range_overflow_safe(e, periods, stride, side="end")
    else:
        raise ValueError(
            "at least 'start' or 'end' should be specified if a 'period' is given."
        )

    return range_to_ndarray(range(b, e, stride))


def generate_daily_offset_range(
    start: Timestamp | None,
    end: Timestamp | None,
    periods: int | None,
    freq: BaseOffset,
    unit: TimeUnit = "ns",
) -> npt.NDArray[np.int64]:
    """
    Generate a range for offsets whose on-offset dates are a subset of a
    daily grid, by generating a daily range and filtering.

    This is a performance optimization (GH#16463) for offsets like BusinessDay

View on GitHub (pinned to 3b7651241d)

Solutions

  1. Provide `start` together with `periods`, or `end` together with `periods`, or both `start` and `end`.
  2. If `periods` is None, supply both `start` and `end`.
  3. Add an upstream assert: `assert start is not None or end is not None` before calling `date_range`.

Example fix

// before
pd.date_range(periods=5, freq='D')   # no start/end -> ValueError

// after
pd.date_range(start='2020-01-01', periods=5, freq='D')
Defensive patterns

Strategy: validation

Validate before calling

if start is None and end is None:
    raise ValueError('date_range needs start or end (or both with periods=None)')
pd.date_range(start=start, end=end, periods=periods, freq=freq)

Type guard

def has_range_inputs(start, end, periods) -> bool:
    return (start is not None and periods is not None) or (end is not None and periods is not None) or (start is not None and end is not None)

Try / catch

try:
    rng = pd.date_range(start=start, periods=periods, freq=freq)
except ValueError as e:
    if "at least 'start' or 'end'" in str(e):
        raise ValueError('Pass start= or end= alongside periods=') from e
    raise

Prevention

When it happens

Trigger: Calling `pd.date_range(periods=N)` without `start` or `end`; calling `pd.date_range(start=..., periods=None, end=None)` (only start); calling `pd.date_range()` with none of the three. The error surfaces from the regular-range generator used by `date_range` for fixed-frequency offsets.

Common situations: Variable confusion (passing `periods` as positional but it lands in a different slot); building ranges programmatically where `start` and `end` are both None at runtime; refactoring that dropped a required argument.

Related errors


AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11). Data as JSON: /api/errors/1995e78bdfa5d787. Report an issue: GitHub.