Hmbown/CodeWhale · error
duration resolved to zero seconds
Error message
duration {s:?} resolved to zero seconds What it means
parse_duration_secs parses human duration strings like '2h30m' into a total number of seconds. It throws this error when the parsed components sum to zero (e.g. '0m', '0', or an empty numeric input), because a zero-length duration is meaningless for the caller (parse_since computes a 'since' timestamp from it) and would otherwise silently produce a full-history or degenerate query.
Solutions
- Pass a non-zero duration value, e.g. `--since 24h`, `--since 30m`, `--since 7d`.
- Check the shell variable feeding --since; a default of 0/0s must be replaced with a meaningful default.
- If you genuinely want 'everything since epoch', pass an explicit absolute timestamp instead of a zero duration, if supported by parse_since.
Example fix
// before
codewhale-metrics --since $WINDOW # WINDOW="0h"
// after
codewhale-metrics --since ${WINDOW:-24h} # guard against empty/zero default Defensive patterns
Strategy: validation
Validate before calling
let s = duration_str.trim();
if s.is_empty() || s == "0" || s == "0s" || s == "0m" || s == "0h" {
return Err(anyhow::anyhow!("--since needs a non-zero duration, e.g. 24h"));
} Type guard
fn is_nonzero_duration(s: &str) -> bool {
parse_duration_secs(s).map(|v| v > 0).unwrap_or(false)
} Prevention
- Give shell variables feeding --since a non-zero default (e.g. ${WINDOW:-24h}).
- Never pass a bare 0 or unit-less 0 to duration arguments.
- Validate user-supplied durations in scripts before invoking the CLI.
When it happens
Trigger: Calling parse_since with a duration string whose numeric components total 0, e.g. `--since 0`, `--since 0s`, `--since 0h`, or input where the parsing path ends with total == 0.
Common situations: Scripting the metrics CLI with a variable that defaults to '0' or '0m' instead of a real duration; copy-pasting an example with a placeholder 0 value; forgetting the unit multiplier logic and assuming '0h' means 'now'.
Understand the failure class
Background: "invalid duration" / "failed to parse duration": why your timeout, interval, or TTL string is rejected and which formats each library accepts — this error's family across 32 libraries.
Related errors
- Choose one input source, an unused --output path (or…
- --days must be an integer from 1 through 90
- invalid duration component
- invalid value ' ' for '--provider ': expected one of …
- --max-passes applies only to --pr reviews
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/62adc2d2df419a38.
Report an issue: GitHub.
Appendix: source
Thrown at crates/cli/src/metrics.rs:131
'h' => 3_600,
'm' => 60,
's' => 1,
_ => unreachable!(),
};
total += n * factor;
}
_ => anyhow::bail!("unrecognised character {ch:?} in duration {s:?}"),
}
}
if !num_buf.is_empty() {
// Trailing bare number — treat as seconds.
let n: i64 = num_buf.parse()?;
total += n;
}
if total == 0 {
anyhow::bail!("duration {s:?} resolved to zero seconds");
}
Ok(total)
}
// ──────────────────────────────────────────────────────────────────────────────
// Rollup data model
// ──────────────────────────────────────────────────────────────────────────────
/// Per-tool aggregated counters.
#[derive(Debug, Default, serde::Serialize)]
pub struct ToolStats {
pub calls: u64,
/// Calls that were auto-approved (no prompt required).
pub auto_approved: u64,
/// Calls that required a manual prompt.
pub prompted: u64,
/// Total elapsed ms (from events that carry this field).View on GitHub (pinned to 73e0f67d83)