pandas-dev/pandas · error · ValueError

'unit' must be one of 's', 'ms', 'us', 'ns'

Error message

'unit' must be one of 's', 'ms', 'us', 'ns'

What it means

TimedeltaArray._generate_range restricts the unit parameter to the supported set {s, ms, us, ns}. Coarser (e.g. minute, hour, day) or finer (ns below) units are not allowed for the array's internal storage resolution; only the resolutions supported by numpy timedelta64 without overflow are accepted.

Solutions

  1. Use one of 's', 'ms', 'us', 'ns' for the unit argument.
  2. If you need day/hour/minute granularity, specify freq in those units (e.g. freq='1D') but keep unit in the supported set.
  3. Post-process with .as_unit(...) if a different display unit is desired.

Example fix

// before
pd.timedelta_range('1 day', periods=3, freq='1D', unit='D')  # ValueError
// after
pd.timedelta_range('1 day', periods=3, freq='1D', unit='s')
Defensive patterns

Strategy: validation

Validate before calling

SUPPORTED_UNITS = {'s','ms','us','ns'}
def validate_td_unit(unit):
    if unit not in SUPPORTED_UNITS:
        raise ValueError(f"unit must be one of {SUPPORTED_UNITS}, got {unit!r}")
    return unit

Type guard

def is_supported_td_unit(unit) -> bool:
    return unit in {'s','ms','us','ns'}

Try / catch

try:
    pd.timedelta_range(start, periods=periods, freq=freq, unit=unit)
except ValueError as e:
    if "'unit' must be one of" in str(e):
        pd.timedelta_range(start, periods=periods, freq=freq, unit='s')
    else:
        raise

Prevention

When it happens

Trigger: pd.timedelta_range(..., unit='m'); passing unit='h' or unit='D' to _generate_range; constructing with a custom TimeUnit outside {s,ms,us,ns}.

Common situations: Assuming unit accepts the same strings as to_timedelta (which accepts 'D','h','m'); reusing a unit string parsed from user config without validation.

Related errors


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

Appendix: source

Thrown at pandas/core/arrays/timedeltas.py:317

    ) -> 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"
            )

        if start is not None:
            start = Timedelta(start).as_unit("ns")

        if end is not None:
            end = Timedelta(end).as_unit("ns")

        if unit not in ["s", "ms", "us", "ns"]:
            raise ValueError("'unit' must be one of 's', 'ms', 'us', 'ns'")

        if start is not None and unit is not None:
            start = start.as_unit(unit, round_ok=False)
        if end is not None and unit is not None:
            end = end.as_unit(unit, round_ok=False)

        left_closed, right_closed = validate_endpoints(closed)

        if freq is not None:
            index = generate_regular_range(start, end, periods, freq, unit=unit)
        else:
            index = np.linspace(start._value, end._value, periods).astype("i8")

        if not left_closed:
            index = index[1:]
        if not right_closed:
            index = index[:-1]

View on GitHub (pinned to 3b7651241d)