can1357/oh-my-pi · error

duration is too large: {value}

Error message

duration is too large: {value}

What it means

Raised in `parse_time_filter` when a duration-style filter value (e.g. `7d`) parses to a `Duration` that cannot be subtracted from `SystemTime::now()` — `checked_sub` returns None because the result would predate the clock's representable minimum (year 0 on most platforms). The library reports `duration is too large: {value}` as `InvalidInput`, meaning the requested look-back window is absurdly long, not that the duration syntax was wrong.

Source

Thrown at crates/pi-builtins/src/fd.rs:1345

			));
		},
	};
	let bytes = count.checked_mul(multiplier).ok_or_else(|| {
		io::Error::new(io::ErrorKind::InvalidInput, format!("size is too large: {value}"))
	})?;
	Ok(SizeFilter { ordering, bytes })
}

fn parse_time_filter(value: &str) -> io::Result<SystemTime> {
	if let Some(timestamp) = value.strip_prefix('@') {
		let seconds = timestamp
			.parse::<u64>()
			.map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err.to_string()))?;
		return Ok(UNIX_EPOCH + Duration::from_secs(seconds));
	}
	if let Some(duration) = parse_duration(value)? {
		return SystemTime::now().checked_sub(duration).ok_or_else(|| {
			io::Error::new(io::ErrorKind::InvalidInput, format!("duration is too large: {value}"))
		});
	}
	parse_utc_datetime(value)
}

fn parse_duration(value: &str) -> io::Result<Option<Duration>> {
	let trimmed = value.trim();
	let split = trimmed
		.char_indices()
		.find(|(_, ch)| !ch.is_ascii_digit())
		.map_or(trimmed.len(), |(index, _)| index);
	if split == 0 || split == trimmed.len() {
		return Ok(None);
	}
	let count = trimmed[..split]
		.parse::<u64>()
		.map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err.to_string()))?;
	let unit = trimmed[split..].to_ascii_lowercase();

View on GitHub (pinned to 9690622007)

Solutions

  1. Check the duration value for extra digits or a wrongly concatenated number and correct it to a sane window (seconds/minutes/hours/days/weeks).
  2. Use a smaller unit so the total stays within a realistic range, e.g. `30d` rather than a centuries-long span.
  3. For a fixed historical cutoff, use an absolute form instead: `@<epoch-seconds>` or `YYYY-MM-DD[ HH:MM:SS]` (UTC), which bypasses the now-minus-duration arithmetic entirely.

Example fix

// before (absurd look-back)
find --changed 99999999999999w
// after
find --changed 30d
find --changed @1609459200
Defensive patterns

Strategy: validation

Validate before calling

fn validate_duration_filter(value: &str) -> Result<(), String> {
    let trimmed = value.trim();
    let split = trimmed
        .find(|c: char| !c.is_ascii_digit())
        .unwrap_or(trimmed.len());
    if split == 0 || split == trimmed.len() {
        return Ok(()); // not a duration; other parse paths apply
    }
    let count: u64 = trimmed[..split]
        .parse()
        .map_err(|e| format!("bad duration count: {e}"))?;
    let unit = trimmed[split..].to_ascii_lowercase();
    let secs = match unit.as_str() {
        "s" | "sec" | "secs" | "second" | "seconds" => count,
        "m" | "min" | "mins" | "minute" | "minutes" => count.saturating_mul(60),
        "h" | "hr" | "hrs" | "hour" | "hours" => count.saturating_mul(3600),
        "d" | "day" | "days" => count.saturating_mul(86_400),
        "w" | "week" | "weeks" => count.saturating_mul(604_800),
        _ => return Ok(()),
    };
    // A sane look-back bound; anything near i64/SystemTime limits will fail checked_sub.
    if secs > 100 * 365 * 86_400 {
        return Err(format!("duration too large: {value}"));
    }
    Ok(())
}

Try / catch

match parse_time_filter(input) {
    Ok(time) => use_time(time),
    Err(e) if e.to_string().starts_with("duration is too large") => {
        eprintln!("look-back window '{input}' exceeds representable time range; use a smaller duration or an absolute date");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: A duration filter value with a unit parsed by `parse_duration` whose total seconds exceed the platform's SystemTime range backwards from now — practically this needs an enormous count like `99999999999999999d`; note the multiplication saturates per unit, so the huge total only fails at `checked_sub`.

Common situations: Fat-fingered extra digits in a duration (`3000000000000000d` instead of `30d`); constructing the duration programmatically by concatenating a variable that already contains seconds with a `d` suffix; misconfigured defaults in scripts that build filter strings dynamically.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/511fea05623d2113. Report an issue: GitHub.