pandas-dev/pandas · error · TypeError

periods must be an integer, got {periods}

Error message

periods must be an integer, got {periods}

What it means

Raised by validate_periods, the helper used by date_range/time_range/_generate_range, when the periods argument is not None and not an integer. 'periods' names the count of samples in the generated range, so a float, string, or numpy float would be ambiguous.

Source

Thrown at pandas/core/arrays/datetimelike.py:2507

    """
    If a `periods` argument is passed to the Datetime/Timedelta Array/Index
    constructor, cast it to an integer.

    Parameters
    ----------
    periods : None, int

    Returns
    -------
    periods : None or int

    Raises
    ------
    TypeError
        if periods is not None or int
    """
    if periods is not None and not lib.is_integer(periods):
        raise TypeError(f"periods must be an integer, got {periods}")
    # error: Incompatible return value type (got "int | integer[Any] | None",
    # expected "int | None")
    return periods  # type: ignore[return-value]


def dtype_to_unit(dtype: DatetimeTZDtype | np.dtype | ArrowDtype) -> str:
    """
    Return the unit str corresponding to the dtype's resolution.

    Parameters
    ----------
    dtype : DatetimeTZDtype or np.dtype
        If np.dtype, we assume it is a datetime64 dtype.

    Returns
    -------
    str
    """

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Coerce periods to int before passing: pd.date_range(..., periods=int(periods)).
  2. Validate inputs from config with int(str(periods)) once at load time.
  3. If periods was meant to be a count from a division, wrap with int(round(...)).

Example fix

# before
pd.date_range('2020-01-01', periods=df.shape[0] / 2, freq='D')

# after
pd.date_range('2020-01-01', periods=int(df.shape[0] / 2), freq='D')
Defensive patterns

Strategy: validation

Validate before calling

if periods is not None and not isinstance(periods, (int, np.integer)):
    periods = int(periods)
# or simply: periods = int(periods) if periods is not None else None

Type guard

def is_int_periods(p) -> bool:
    return p is None or isinstance(p, (int, np.integer))

Try / catch

try:
    pd.date_range(start, end, periods=periods, freq='D')
except TypeError as e:
    if 'periods must be an integer' in str(e):
        pd.date_range(start, end, periods=int(periods), freq='D')
    else: raise

Prevention

When it happens

Trigger: pd.date_range(start, end, periods=10.0), pd.date_range(periods='5', freq='D', start=...), periods read from a config/JSON value that parsed as float (e.g. 5.0) or string ('5').

Common situations: Config-driven parameter passing where periods comes from YAML/JSON without int coercion; dividing two ints to scale a count producing a float; np.int64 usually passes (lib.is_integer accepts numpy integers) but np.float64 does not.

Related errors


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