can1357/oh-my-pi · error

size is too large: {value}

Error message

size is too large: {value}

What it means

After resolving the unit multiplier, parse_size_filter computes count * multiplier with u64::checked_mul. If the product overflows u64 (e.g. a large count with the t = 1,000,000,000,000 multiplier), the computation is refused and this io::Error with ErrorKind::InvalidInput naming the original value is thrown. This prevents silent wraparound in size comparisons.

Source

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

	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}"),
			));
		},
	};
	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)
}

View on GitHub (pinned to 9690622007)

Solutions

  1. Lower the count: any practical size fits — '1000t' (10^15 bytes) is fine, but check count*multiplier ≤ 18446744073709551615
  2. Express the threshold in a larger unit rather than a huge count in a small unit
  3. To match 'all files above X', pick a realistic ceiling (e.g. '+10t') instead of a sentinel huge value
  4. Pre-check in code: parse the count as u64 and compare against u64::MAX / multiplier before calling

Example fix

// before
fd --size '+99999999999999999999'   // overflows with multiplier
// after
fd --size '+99t'  // 99 terabytes, well within u64
Defensive patterns

Strategy: validation

Validate before calling

const MULTIPLIERS: Record<string, number> = { "":1, 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 };
function validateSizeFits(value: string): string | null {
  const m = /^([+-]?)(\d+)(.*)$/.exec(value);
  if (!m) return null;
  const count = BigInt(m[2]); const mult = BigInt(MULTIPLIERS[m[3].toLowerCase()] ?? 1);
  return count * mult > 18446744073709551615n ? `size is too large: ${value}` : null;
}

Try / catch

try {
  await runFd({ size: value });
} catch (err) {
  if (err instanceof Error && err.message.startsWith("size is too large: ")) {
    console.error(`${err.message} — count*unit exceeds u64; pick a smaller count or bigger unit.`);
  } else throw err;
}

Prevention

When it happens

Trigger: Passing a --size whose digit count times its unit exceeds u64::MAX: e.g. '+18446744073710t' (≈1.8e22 bytes), '99999999999ti' (≈1.1e14 × ... overflow), or even a 20-digit count with any multiplier above 1. The digit-run parse (error 32) succeeds here; the overflow happens at multiplication.

Common situations: Users intending 'infinite' or 'no upper bound' sizes by typing an enormous number instead of omitting the + filter; generated scripts computing byte thresholds in a float-typed variable then formatting with full precision; confusion of petabyte-scale values with byte counts.

Related errors


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