locustio/locust · error · ValueError
Invalid time span format. Valid formats: 20, 20s, 3m, 2h, 1h
Error message
Invalid time span format. Valid formats: 20, 20s, 3m, 2h, 1h20m, 3h30m10s, etc.
What it means
After regex matching, parse_timespan verifies the whole string matched the pattern (group(0) == time_str). Strings containing unsupported characters, units (d/w), signs, or partial matches raise this ValueError with the list of valid formats. Note an all-optional regex can also produce an empty match, which is caught later at line 23.
Source
Thrown at locust/util/timespan.py:20
from datetime import timedelta
def parse_timespan(time_str) -> int:
"""
Parse a string representing a time span and return the number of seconds.
Valid formats are: 20, 20s, 3m, 2h, 1h20m, 3h30m10s, etc.
"""
if not time_str:
raise ValueError("Invalid time span format")
if re.match(r"^\d+$", time_str):
# if an int is specified we assume they want seconds
return int(time_str)
timespan_regex = re.compile(r"((?P<hours>\d+?)h)?((?P<minutes>\d+?)m)?((?P<seconds>\d+?)s)?")
parts = timespan_regex.match(time_str)
if not parts or parts.group(0) != time_str:
raise ValueError("Invalid time span format. Valid formats: 20, 20s, 3m, 2h, 1h20m, 3h30m10s, etc.")
time_params = {name: int(value) for name, value in parts.groupdict().items() if value}
if not time_params:
raise ValueError("Invalid time span format. Valid formats: 20, 20s, 3m, 2h, 1h20m, 3h30m10s, etc.")
return int(timedelta(**time_params).total_seconds())
View on GitHub (pinned to f391a716e1)
Solutions
- Rewrite the duration using only supported units, e.g. '1d' → '24h', '1.5h' → '1h30m'
- Strip whitespace and lowercase the input before passing it
- Add your own pre-validation/normalization if you need days or weeks (convert to hours/minutes first)
- Update the CLI/config value to one of: 20, 20s, 3m, 2h, 1h20m, 3h30m10s
Example fix
# before locust --run-time=1d # after locust --run-time=24h
Defensive patterns
Strategy: validation
Validate before calling
import re
RUNTIME_RE = re.compile(r'^\d+(?:\d*h)?(?:\d*m)?(?:\d*s)?$')
def is_valid_timespan(s):
return bool(RUNTIME_RE.fullmatch(s)) # then strip/lower before parse_timespan Try / catch
try:
seconds = parse_timespan(run_time.strip().lower())
except ValueError as e:
log.error('%s — use formats like 20, 20s, 3m, 2h, 1h20m, 3h30m10s', e)
sys.exit(2) Prevention
- Only use digits plus h/m/s units; convert days to hours yourself
- Normalize input with .strip().lower() before parsing
- Avoid fractional durations; write '1h30m' instead of '1.5h'
- Unit-test your config parsing with the same formats you ship in config files
When it happens
Trigger: parse_timespan('1d'), parse_timespan('2H') (uppercase), parse_timespan('3m30') (trailing unitless digits), parse_timespan('-5m'), or any string with whitespace/typos like ' 3m'.
Common situations: Users assuming day/week units are supported (they are not — only h/m/s); uppercase unit letters; stray spaces from config parsing; fractional durations like '1.5h'.
Related errors
- Invalid time span format
- Unrecognized task type in user
- The following user classes have the same class name: {}
- No tag name was supplied
AI-assisted analysis of locustio/locust@f391a716e1 (2026-08-29).
Data as JSON: /api/errors/3553321d838f4675.
Report an issue: GitHub.