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

Raised by TimedeltaArray._generate_range when the `unit` argument is not one of the supported resolutions 's','ms','us','ns'. TimedeltaArray is backed by int64 nanosecond-or-coarser ticks, and only those four resolutions are representable; any other string (e.g. 'm' for minutes, 'h', or a typo) is rejected before range generation proceeds.

Source

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

    ) -> 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 71959b8cb9)

Solutions

  1. Use one of 's','ms','us','ns' for the unit argument.
  2. If you want minute/hour granularity, express it via freq='1min'/'1H' instead of unit.
  3. Pick the coarsest unit that fits your precision need to reduce memory.

Example fix

# before
pd.timedelta_range('1 day', periods=3, unit='m')  # ValueError
# after
pd.timedelta_range('1 day', periods=3, freq='1min')
# or: 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:
    return pd.timedelta_range(start, periods=3, unit=unit)
except ValueError as e:
    if "'unit' must be one of" in str(e):
        return pd.timedelta_range(start, periods=3, unit='s')
    raise

Prevention

When it happens

Trigger: Calling timedelta_range(..., unit='m'), unit='minutes', or unit='h'; passing a custom unit string. The check at timedeltas.py:299 is `unit not in ['s','ms','us','ns']`.

Common situations: Confusing freq strings (which accept '1H','30min') with unit strings (which only take s/ms/us/ns); passing a numpy unit abbreviation by mistake; schema/config typos.

Related errors


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