benfred/py-spy · error
invalid duration
Error message
invalid duration
What it means
This panic comes from parsing the --duration CLI option for the `record` subcommand. py-spy accepts "unlimited" or a number of seconds; any other value is parsed with u64::from_str and the failed parse panics with "invalid duration" via expect().
Source
Thrown at src/config.rs:395
let mut config = Config::default();
let (subcommand, matches) = matches.subcommand().unwrap();
// Check if `--native` was used on an unsupported platform
if subcommand != "completions" && !cfg!(feature = "unwind") && matches.get_flag("native") {
eprintln!(
"Collecting stack traces from native extensions (`--native`) is not supported on your platform."
);
std::process::exit(1);
}
match subcommand {
"record" => {
config.sampling_rate = *matches.get_one("rate").unwrap();
config.duration = match matches.get_one::<String>("duration").map(|d| d.as_str()) {
Some("unlimited") | None => RecordDuration::Unlimited,
Some(seconds) => {
RecordDuration::Seconds(seconds.parse().expect("invalid duration"))
}
};
config.format = matches.get_one("format").copied();
config.filename = matches.get_one::<String>("output").cloned();
config.show_line_numbers = !matches.get_flag("nolineno");
config.lineno = if matches.get_flag("nolineno") {
LineNo::NoLine
} else if matches.get_flag("function") {
LineNo::First
} else {
LineNo::LastInstruction
};
config.include_thread_ids = matches.get_flag("threads");
if matches.get_flag("nolineno") && matches.get_flag("function") {
eprintln!("--function & --nolinenos can't be used together");
std::process::exit(1);
}
config.hide_progress = matches.get_flag("hideprogress");View on GitHub (pinned to 32080cc0c2)
Solutions
- Pass the duration as plain seconds: `py-spy record --duration 300` instead of `--duration 5m`.
- Use `--duration unlimited` (or omit --duration) for open-ended recording, and stop the process with Ctrl-C to write the output.
- Convert minutes/hours to seconds in your wrapper script before invoking py-spy.
- Patch config.rs to parse duration suffixes if you build py-spy from source.
Example fix
// before py-spy record --duration 5m -o profile.svg --pid 1234 // after py-spy record --duration 300 -o profile.svg --pid 1234
Defensive patterns
Strategy: validation
Validate before calling
case "$DURATION" in unlimited|'') ;; *[!0-9]*|[!0-9]*) echo "--duration must be 'unlimited' or plain seconds" >&2; exit 1 ;; esac
Prevention
- Always pass --duration as a bare integer number of seconds.
- Use 'unlimited' (or omit the flag) for open-ended recordings.
- Convert units (m/h) to seconds in wrapper scripts before invoking py-spy.
When it happens
Trigger: Running `py-spy record --duration <value>` where value is neither "unlimited" nor omitted and does not parse as an unsigned integer (e.g. "30s", "1m", "0.5", "ten").
Common situations: Users pass human-friendly durations like "--duration 5m" or "--duration 30s" out of habit from tools like timeout or fluentd; or wrap the number in quotes/units by mistake in scripts.
Related errors
AI-assisted analysis of benfred/py-spy@32080cc0c2 (2026-09-05).
Data as JSON: /api/errors/035c3f77fc7b2e75.
Report an issue: GitHub.