spacedriveapp/spacedrive · error · anyhow::Error

Invalid duration format: {}

Error message

Invalid duration format: {}

What it means

Thrown by parse_duration() when the duration part of an 'ago' expression does not split (on whitespace) into exactly two tokens: a number and a unit. It is reached from parse_time_filter() after stripping the trailing ' ago' (4 characters), so '10 minutes ago' -> '10 minutes' parses, while malformed remainders do not.

Source

Thrown at apps/cli/src/domains/sync/mod.rs:156

		let duration = parse_duration(duration_str)?;
		Ok(Utc::now() - duration)
	} else {
		// Try parsing as absolute time
		DateTime::parse_from_rfc3339(time_str)
			.map(|dt| dt.with_timezone(&Utc))
			.or_else(|_| {
				// Try common formats
				DateTime::parse_from_str(time_str, "%Y-%m-%d %H:%M:%S")
					.map(|dt| dt.with_timezone(&Utc))
			})
			.map_err(|_| anyhow::anyhow!("Invalid time format: {}", time_str))
	}
}

fn parse_duration(duration_str: &str) -> Result<chrono::Duration> {
	let parts: Vec<&str> = duration_str.split_whitespace().collect();
	if parts.len() != 2 {
		return Err(anyhow::anyhow!("Invalid duration format: {}", duration_str));
	}

	let value: i64 = parts[0]
		.parse()
		.map_err(|_| anyhow::anyhow!("Invalid number: {}", parts[0]))?;
	let unit = parts[1].to_lowercase();

	let seconds = match unit.as_str() {
		"second" | "seconds" | "sec" | "s" => value,
		"minute" | "minutes" | "min" | "m" => value * 60,
		"hour" | "hours" | "h" => value * 3600,
		"day" | "days" | "d" => value * 86400,
		"week" | "weeks" | "w" => value * 604800,
		_ => return Err(anyhow::anyhow!("Unknown time unit: {}", unit)),
	};

	Ok(chrono::Duration::seconds(seconds))
}

View on GitHub (pinned to 6dfeccf211)

Solutions

  1. Use exactly one space between number and unit: --since '5 minutes ago'
  2. Remove filler words and extra whitespace from the expression
  3. Switch to an absolute timestamp if spacing is hard to control in your shell
Defensive patterns

Strategy: validation

Validate before calling

let tokens: Vec<&str> = duration_str.split_whitespace().collect();
if tokens.len() != 2 {
    eprintln!("Duration must be exactly '<number> <unit>', e.g. '30 minutes'");
    return Ok(());
}

Type guard

fn is_wellformed_duration(d: &str) -> bool {
    let mut it = d.split_whitespace();
    matches!((it.next(), it.next(), it.next()), (Some(_), Some(_), None))
}

Prevention

When it happens

Trigger: --since '5minutes ago' (no space), '--since "5 minutes ago"' (double space yields 3 tokens), '--since ago' (empty remainder), or any extra words like '--since "about 5 minutes ago"' (3 tokens).

Common situations: Shell quoting that collapses or mangles spaces; users adding filler words; trailing whitespace inside the quoted string.

Related errors


AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16). Data as JSON: /api/errors/af91b36d04abafb2. Report an issue: GitHub.