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 in _generate_range when the unit keyword is not one of the four valid storage resolutions ('s','ms','us','ns'). This controls the i8 precision of the generated datetime64 backing array; coarser/finer aliases are not valid storage units.
Source
Thrown at pandas/core/arrays/datetimes.py:426
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"
)
freq = to_offset(freq)
if start is not None:
start = Timestamp(start)
if end is not None:
end = Timestamp(end)
if start is NaT or end is NaT:
raise ValueError("Neither `start` nor `end` can be NaT")
if unit is not None:
if unit not in ["s", "ms", "us", "ns"]:
raise ValueError("'unit' must be one of 's', 'ms', 'us', 'ns'")
else:
unit = "ns"
if start is not None:
start = start.as_unit(unit, round_ok=False)
if end is not None:
end = end.as_unit(unit, round_ok=False)
left_inclusive, right_inclusive = validate_inclusive(inclusive)
start, end = _maybe_normalize_endpoints(start, end, normalize)
tz = _infer_tz_from_endpoints(start, end, tz)
if tz is not None:
# Localize the start and end arguments
start = _maybe_localize_point(start, freq, tz, ambiguous, nonexistent)
end = _maybe_localize_point(end, freq, tz, ambiguous, nonexistent)
if freq is not None:View on GitHub (pinned to 71959b8cb9)
Solutions
- Pass unit='s'|'ms'|'us'|'ns' to set storage precision.
- For minute/hourly spacing use freq='min'|'h' instead of unit.
- If you genuinely need coarser-than-second storage, store in 's' and downcast at display time.
Example fix
# before
pd.date_range('2020-01-01', periods=3, freq='D', unit='m')
# after
pd.date_range('2020-01-01', periods=3, freq='min', unit='s') Defensive patterns
Strategy: validation
Validate before calling
VALID_UNITS = {'s','ms','us','ns'}
if unit not in VALID_UNITS:
raise ValueError(f'unit must be one of {VALID_UNITS}, got {unit!r}') Type guard
from typing import Literal
def is_storage_unit(u: str) -> bool:
return u in {'s','ms','us','ns'} Try / catch
try:
pd.date_range(start, periods=3, freq='D', unit=unit)
except ValueError as e:
if "'unit' must be one of" in str(e):
pd.date_range(start, periods=3, freq='D', unit='ns')
else: raise Prevention
- Type unit as Literal['s','ms','us','ns'] in signatures.
- Use freq= for spacing and unit= for precision; never conflate.
When it happens
Trigger: pd.date_range(..., unit='m'), pd.date_range(..., unit='us5'), pd.date_range(..., unit='ps'), or passing a frequency alias like 'h'/'T' as unit.
Common situations: Confusing the unit= parameter (storage resolution) with the freq= parameter (grid spacing). Copying unit strings from numpy dtype expressions like 'datetime64[m]'. Wanting minute/hour spacing.
Related errors
- Supported units are 's', 'ms', 'us', 'ns'
- periods must be an integer, got {periods}
- Must provide freq argument if no data is supplied
- Of the four parameters: start, end, periods, and freq, exact
- Neither `start` nor `end` can be NaT
AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07).
Data as JSON: /api/errors/eb025f3518c3f748.
Report an issue: GitHub.