{"record":{"id":"711381b191be5075","repo":"pandas-dev/pandas","slug":"periods-must-be-an-integer-got-periods","errorCode":null,"errorMessage":"periods must be an integer, got {periods}","messagePattern":"periods must be an integer, got (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/datetimelike.py","lineNumber":2507,"sourceCode":"    \"\"\"\n    If a `periods` argument is passed to the Datetime/Timedelta Array/Index\n    constructor, cast it to an integer.\n\n    Parameters\n    ----------\n    periods : None, int\n\n    Returns\n    -------\n    periods : None or int\n\n    Raises\n    ------\n    TypeError\n        if periods is not None or int\n    \"\"\"\n    if periods is not None and not lib.is_integer(periods):\n        raise TypeError(f\"periods must be an integer, got {periods}\")\n    # error: Incompatible return value type (got \"int | integer[Any] | None\",\n    # expected \"int | None\")\n    return periods  # type: ignore[return-value]\n\n\ndef dtype_to_unit(dtype: DatetimeTZDtype | np.dtype | ArrowDtype) -> str:\n    \"\"\"\n    Return the unit str corresponding to the dtype's resolution.\n\n    Parameters\n    ----------\n    dtype : DatetimeTZDtype or np.dtype\n        If np.dtype, we assume it is a datetime64 dtype.\n\n    Returns\n    -------\n    str\n    \"\"\"","sourceCodeStart":2489,"sourceCodeEnd":2525,"githubUrl":"https://github.com/pandas-dev/pandas/blob/71959b8cb9b2459c16e14b34f28b178ccfe14735/pandas/core/arrays/datetimelike.py#L2489-L2525","documentation":"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.","triggerScenarios":"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').","commonSituations":"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.","solutions":["Coerce periods to int before passing: pd.date_range(..., periods=int(periods)).","Validate inputs from config with int(str(periods)) once at load time.","If periods was meant to be a count from a division, wrap with int(round(...))."],"exampleFix":"# before\npd.date_range('2020-01-01', periods=df.shape[0] / 2, freq='D')\n\n# after\npd.date_range('2020-01-01', periods=int(df.shape[0] / 2), freq='D')","handlingStrategy":"validation","validationCode":"if periods is not None and not isinstance(periods, (int, np.integer)):\n    periods = int(periods)\n# or simply: periods = int(periods) if periods is not None else None","typeGuard":"def is_int_periods(p) -> bool:\n    return p is None or isinstance(p, (int, np.integer))","tryCatchPattern":"try:\n    pd.date_range(start, end, periods=periods, freq='D')\nexcept TypeError as e:\n    if 'periods must be an integer' in str(e):\n        pd.date_range(start, end, periods=int(periods), freq='D')\n    else: raise","preventionTips":["Coerce config-sourced counts to int at load time.","Type periods as int|None in your function signatures."],"tags":["date-range","constructor","validation","type-error"],"analyzedSha":"71959b8cb9b2459c16e14b34f28b178ccfe14735","analyzedAt":"2026-08-07T01:30:20.476Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}