can1357/oh-my-pi · error · io::Error

missing {name}

Error message

missing {name}

What it means

parse_i32_part extracts a signed 32-bit date component (e.g. year) from an Option<&str> produced by splitting a date string. When the expected component is absent (None), it throws InvalidInput with 'missing {name}' where name identifies which part (year, etc.) was expected. It also converts any parse failure of the present string into an InvalidInput error.

Source

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

		|| minute > 59
		|| second > 59
	{
		return Err(io::Error::new(io::ErrorKind::InvalidInput, format!("invalid date: {value}")));
	}
	let days = days_from_civil(year, month, day);
	let seconds = days
		.checked_mul(86_400)
		.and_then(|base| base.checked_add(i64::from(hour * 3_600 + minute * 60 + second)))
		.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "date is out of range"))?;
	if seconds < 0 {
		return Err(io::Error::new(io::ErrorKind::InvalidInput, "dates before 1970 are unsupported"));
	}
	Ok(UNIX_EPOCH + Duration::from_secs(u64::try_from(seconds).unwrap_or(u64::MAX)))
}

fn parse_i32_part(value: Option<&str>, name: &str) -> io::Result<i32> {
	value
		.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, format!("missing {name}")))?
		.parse::<i32>()
		.map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err.to_string()))
}

fn parse_u32_part(value: Option<&str>, name: &str) -> io::Result<u32> {
	value
		.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, format!("missing {name}")))?
		.parse::<u32>()
		.map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err.to_string()))
}

fn days_from_civil(year: i32, month: u32, day: u32) -> i64 {
	let year = year - i32::from(month <= 2);
	let era = if year >= 0 { year } else { year - 399 } / 400;
	let year_of_era = year - era * 400;
	let month = i32::try_from(month).unwrap_or(0);
	let day = i32::try_from(day).unwrap_or(0);
	let day_of_year = (153 * (month + if month > 2 { -3 } else { 9 }) + 2) / 5 + day - 1;

View on GitHub (pinned to 9690622007)

Solutions

  1. Supply the full date including the year, e.g. '1997-12-25'
  2. Check the expected date format documented for the fd builtin's filter option
  3. Quote the argument in your shell so dashes/hyphens are not misinterpreted

Example fix

// before
fd --newer '12-25' .
// after
fd --newer '1997-12-25' .
Defensive patterns

Strategy: validation

Validate before calling

fn validate_date_has_year(date: &str) -> Result<(), String> {
	let parts: Vec<&str> = date.split('-').collect();
	if parts.len() < 3 {
		return Err(format!("expected YYYY-MM-DD, got '{date}'"));
	}
	Ok(())
}

Try / catch

match builtin_result {
	Err(e) if e.to_string().starts_with("missing ") => eprintln!("date argument incomplete: {e}"),
	Err(e) => return Err(e),
	Ok(v) => /* ... */,
}

Prevention

When it happens

Trigger: Passing a date string to the fd builtin that lacks a required numeric component, e.g. omitting the year in a date filter so the split yields fewer parts than the parser expects, causing parse_i32_part to receive None for that field.

Common situations: Malformed CLI date arguments like '--newer 12-25' (missing year), locale-dependent date formats with omitted fields, empty date strings after trimming.

Related errors


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