can1357/oh-my-pi · error

err.to_string() (size parse error)

Error message

err.to_string() (size parse error)

What it means

After the digit run is extracted, it is parsed with u64::from_str. If the digit run is longer than 20 digits or otherwise exceeds the u64 range (18446744073709551615), the parse fails and the underlying ParseIntError message ('number too large to fit in target type') is wrapped into an io::Error with ErrorKind::InvalidInput. Note this fires only for the raw count overflow; a valid count times a large unit takes the separate 'size is too large' path.

Source

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

fn parse_size_filter(value: &str) -> io::Result<SizeFilter> {
	let (ordering, rest) = if let Some(rest) = value.strip_prefix('+') {
		(SizeOrdering::GreaterOrEqual, rest)
	} else if let Some(rest) = value.strip_prefix('-') {
		(SizeOrdering::LessOrEqual, rest)
	} else {
		(SizeOrdering::Equal, value)
	};
	let split = rest
		.char_indices()
		.find(|(_, ch)| !ch.is_ascii_digit())
		.map_or(rest.len(), |(index, _)| index);
	if split == 0 {
		return Err(io::Error::new(io::ErrorKind::InvalidInput, format!("invalid size: {value}")));
	}
	let count = rest[..split]
		.parse::<u64>()
		.map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err.to_string()))?;
	let unit = rest[split..].to_ascii_lowercase();
	let multiplier = match unit.as_str() {
		"" | "b" => 1,
		"k" => 1_000,
		"m" => 1_000_000,
		"g" => 1_000_000_000,
		"t" => 1_000_000_000_000,
		"ki" => 1_024,
		"mi" => 1_048_576,
		"gi" => 1_073_741_824,
		"ti" => 1_099_511_627_776,
		_ => {
			return Err(io::Error::new(
				io::ErrorKind::InvalidInput,
				format!("invalid size unit: {unit}"),
			));
		},
	};

View on GitHub (pinned to 9690622007)

Solutions

  1. Reduce the digit count to fit u64 (≤20 digits) — for practical sizes use a unit: '99999999999t' instead of a 23-digit byte count
  2. Inspect the interpolated value in scripts to ensure no extra digits were concatenated
  3. Use a unit multiplier (k/m/g/t) rather than spelling out huge byte counts
  4. Catch the io::Error and validate size strings with a regex like ^[+-]?\d+[a-z]*$ plus a u64 range check before calling

Example fix

// before
fd --size '99999999999999999999999b'
// after
fd --size '100t'  // 100 terabytes, fits u64
Defensive patterns

Strategy: validation

Validate before calling

function validateSizeCount(value: string): string | null {
  const digits = value.replace(/^[+-]/, "").match(/^\d+/)?.[0] ?? "";
  if (digits.length > 20) return `size count too large for u64: ${value}`;
  if (digits.length === 20 && digits > "18446744073709551615") return `size count exceeds u64::MAX: ${value}`;
  return null;
}

Try / catch

try {
  await runFd({ size: value });
} catch (err) {
  if (err instanceof Error && /number too large to fit in target type/.test(err.message)) {
    console.error(`Count exceeds u64 (max 18446744073709551615): ${value}. Use a larger unit.`);
  } else throw err;
}

Prevention

When it happens

Trigger: Passing a --size value whose digit portion exceeds u64::MAX, e.g. '99999999999999999999999b' (23 digits). Any value with more than 20 digits, or exactly u64::MAX+1 like '18446744073709551616'.

Common situations: Accidentally pasting a byte offset or ID into a size flag; a script concatenating values producing an absurdly long number; fat-fingered repeated digits; locale-formatted sizes with digit-group separators are impossible here but a long unseparated string is a common paste artifact.

Understand the failure class

Related errors


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