{"record":{"id":"67f8aa1dc7e73067","repo":"locustio/locust","slug":"invalid-time-span-format","errorCode":null,"errorMessage":"Invalid time span format","messagePattern":"Invalid time span format","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"locust/util/timespan.py","lineNumber":11,"sourceCode":"import re\nfrom datetime import timedelta\n\n\ndef parse_timespan(time_str) -> int:\n    \"\"\"\n    Parse a string representing a time span and return the number of seconds.\n    Valid formats are: 20, 20s, 3m, 2h, 1h20m, 3h30m10s, etc.\n    \"\"\"\n    if not time_str:\n        raise ValueError(\"Invalid time span format\")\n\n    if re.match(r\"^\\d+$\", time_str):\n        # if an int is specified we assume they want seconds\n        return int(time_str)\n\n    timespan_regex = re.compile(r\"((?P<hours>\\d+?)h)?((?P<minutes>\\d+?)m)?((?P<seconds>\\d+?)s)?\")\n    parts = timespan_regex.match(time_str)\n    if not parts or parts.group(0) != time_str:\n        raise ValueError(\"Invalid time span format. Valid formats: 20, 20s, 3m, 2h, 1h20m, 3h30m10s, etc.\")\n    time_params = {name: int(value) for name, value in parts.groupdict().items() if value}\n    if not time_params:\n        raise ValueError(\"Invalid time span format. Valid formats: 20, 20s, 3m, 2h, 1h20m, 3h30m10s, etc.\")\n    return int(timedelta(**time_params).total_seconds())\n","sourceCodeStart":1,"sourceCodeEnd":25,"githubUrl":"https://github.com/locustio/locust/blob/f391a716e12c2c712e80b5835e877b7933397453/locust/util/timespan.py#L1-L25","documentation":"parse_timespan converts a human string like '3h30m' into seconds. If the argument is empty or None (falsy), there is nothing to parse, so it raises this ValueError immediately before regex matching. The `--run-time`/`swarm` option relies on it.","triggerScenarios":"Calling parse_timespan('') or parse_timespan(None); passing --run-time with an empty value, e.g. `locust --run-time=` or swarm(run_time=\"\") programmatically.","commonSituations":"CLI flag configured from an empty environment variable or unfilled config file value; programmatic swarm() calls where run_time was never defaulted.","solutions":["Ensure the run-time value is set and non-empty before passing it (e.g. `run_time or '5m'` default)","Validate the env/config value at startup and fail with a clear message","If an unlimited run is intended, omit the --run-time flag entirely instead of passing an empty string"],"exampleFix":"# before\nrunner.environment.create_locals(); runner.swarm(args.host, run_time=os.environ.get('RUN_TIME',''))\n\n# after\nrun_time = os.environ.get('RUN_TIME')\nif run_time:\n    runner.swarm(args.host, run_time=run_time)","handlingStrategy":"validation","validationCode":"def validate_run_time(v):\n    if not v:\n        raise ValueError('--run-time must be a non-empty string like 20, 20s, 3m, 2h, 1h20m')\n    return v","typeGuard":null,"tryCatchPattern":"try:\n    seconds = parse_timespan(args.run_time)\nexcept ValueError:\n    log.error('--run-time is empty or missing; e.g. --run-time=5m')\n    sys.exit(2)","preventionTips":["Always supply a default for run_time (os.environ.get('RUN_TIME', '5m'))","Omit --run-time entirely rather than passing an empty string","Validate CLI/config inputs at startup before calling swarm()"],"tags":["timespan","cli","validation"],"backgroundTag":"invalid-timespan-format","analyzedSha":"f391a716e12c2c712e80b5835e877b7933397453","analyzedAt":"2026-08-29T00:36:13.872Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}