Hmbown/CodeWhale · warning
invalid duration component
Error message
invalid duration component: {num_buf:?} What it means
parse_duration_secs parses human-friendly duration strings like "1d2h30m". When it accumulates digits and hits a unit character, it tries to parse the accumulated buffer as i64. If the buffer is empty (e.g. "dm") or contains only non-numeric leftover characters, this error is thrown naming the offending buffer with {:?}.
Solutions
- Fix the duration string so every unit (d/h/m/s) is preceded by digits, e.g. "1d2h30m".
- Remove stray non-numeric characters between number and unit.
- If you meant an absolute timestamp, use the timestamp form of --since instead of a duration.
- Quote the value in your shell so spaces do not split the argument.
Example fix
// before --since 1d 2h // buffer becomes empty/garbage between tokens // after --since 1d2h
Defensive patterns
Strategy: validation
Validate before calling
// regex pre-check for well-formed duration const ok = /^(\d+[dhms])+$/.test(value);
Try / catch
try {
let secs = parseSince(raw);
} catch (e) {
if (String(e).includes('invalid duration component')) {
console.error(`Duration must look like 1d2h30m: ${raw}`);
}
} Prevention
- Use the canonical <number><unit> form with no spaces: 1d2h30m.
- Quote duration arguments in shell scripts.
- Only pass timestamps where durations are expected, and vice versa.
When it happens
Trigger: A --since/-since duration value contains a unit character not preceded by a number, e.g. "h30", "1d2m..s", or stray letters like "1dxh" that leave an invalid buffer such as "x".
Common situations: Typo in a CLI --since flag ("since=2hh", "since=1d 2h" with a space producing an empty buffer), or passing a timestamp string where a duration was expected.
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
- unrecognised character
- duration resolved to zero seconds
- invalid header pair ' ', expected name=value
- Invalid input
- unknown argument
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/23a5bf9a3882af6c.
Report an issue: GitHub.
Appendix: source
Thrown at crates/cli/src/metrics.rs:109
pub fn parse_since(s: &str) -> Result<DateTime<Utc>> {
let s = s.trim().to_ascii_lowercase();
let s = s.strip_prefix("now-").unwrap_or(&s);
let secs = parse_duration_secs(s)?;
Ok(Utc::now() - Duration::seconds(secs))
}
fn parse_duration_secs(s: &str) -> Result<i64> {
// Walk through the string accumulating numbers and consuming unit suffixes.
let mut total: i64 = 0;
let mut num_buf = String::new();
for ch in s.chars() {
match ch {
'0'..='9' => num_buf.push(ch),
'd' | 'h' | 'm' | 's' => {
let n: i64 = num_buf
.parse()
.map_err(|_| anyhow::anyhow!("invalid duration component: {num_buf:?}"))?;
num_buf.clear();
let factor = match ch {
'd' => 86_400,
'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;View on GitHub (pinned to 73e0f67d83)