can1357/oh-my-pi · error

invalid size unit: {unit}

Error message

invalid size unit: {unit}

What it means

The size spec's trailing unit (lowercased) must be one of: '' , b, k, m, g, t (decimal 1000-based) or ki, mi, gi, ti (binary 1024-based). Any other suffix — including 'kb', 'mb', 'kib', or a stray character between the digits and unit — throws this io::Error with ErrorKind::InvalidInput. The message reports the exact offending unit string.

Source

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

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

View on GitHub (pinned to 9690622007)

Solutions

  1. Use a bare unit letter for decimal sizes: b, k, m, g, t (e.g. '+10k' = 10,000 bytes)
  2. Use the i-suffixed form for binary sizes: ki, mi, gi, ti (e.g. '+10ki' = 10,240 bytes)
  3. Strip suffixes like 'B'/'iB' doubling: 'kb' → 'k', 'kib' → 'ki'
  4. Pre-validate with a regex such as ^[+-]?(\d+)(b|k|ki|m|mi|g|gi|t|ti)?$ before passing the value

Example fix

// before
fd --size '+10kb'
// after
fd --size '+10k'   // decimal: 10,000 bytes
// or
fd --size '+10ki'  // binary: 10,240 bytes
Defensive patterns

Strategy: validation

Validate before calling

const UNITS = new Set(["","b","k","m","g","t","ki","mi","gi","ti"]);
function validateSizeUnit(value: string): string | null {
  const m = /^[+-]?\d+(.*)$/.exec(value);
  if (!m) return null; // different error path
  const unit = m[1].toLowerCase();
  if (!UNITS.has(unit)) return `invalid size unit: ${unit} (allowed: b k m g t ki mi gi ti)`;
  return null;
}

Type guard

function isValidSizeUnit(u: string): u is ""|"b"|"k"|"m"|"g"|"t"|"ki"|"mi"|"gi"|"ti" {
  return ["","b","k","m","g","t","ki","mi","gi","ti"].includes(u.toLowerCase());
}

Try / catch

try {
  await runFd({ size: value });
} catch (err) {
  if (err instanceof Error && err.message.startsWith("invalid size unit: ")) {
    const unit = err.message.slice("invalid size unit: ".length);
    console.error(`Unknown unit "${unit}". Use b|k|m|g|t (decimal) or ki|mi|gi|ti (binary). "kb"/"kib" are NOT accepted.`);
  } else throw err;
}

Prevention

When it happens

Trigger: Passing '--size +10kb' (only 'k' or 'ki' accepted, not 'kb'), '+5MB' → unit 'mb' unknown, '+1Kib' → 'kib' unknown, or a value like '+10x' with a nonsense unit. Uppercase input is lowercased first, so case is not the issue — spelling is.

Common situations: Users habituated to fd/fd-find or du, which accept 'KB'/'KiB' two-letter forms; scripts carrying sizes from other tools ('1MiB'); copy-pasted sizes with hidden characters between number and unit; confusion between the decimal (k=1000) and binary (ki=1024) ladders.

Related errors


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