can1357/oh-my-pi · error · LnError

extra operand Try ' --help' for more information.

Error message

extra operand {}
Try '{} --help' for more information.

What it means

The ln builtin's ExtraOperand variant fires when more operands are supplied than the link mode accepts. In plain (non-directory-destination) mode ln takes exactly source and destination; a third or later operand triggers this coreutils-style message with a --help hint. The OsString is the offending extra operand and the String is the program name used in the hint.

Solutions

  1. Ensure the final operand is an existing directory when linking multiple sources
  2. Split into multiple ln calls, one per source/destination pair
  3. Remove the extra operand from the argument list

Example fix

// before
ln(&host, &["a.txt", "b.txt", "links/"])?; // if "links/" doesn't exist
// after
std::fs::create_dir("links")?; // or use explicit pairs
ln(&host, &["a.txt", "links/a.txt"])?;
ln(&host, &["b.txt", "links/b.txt"])?;
Defensive patterns

Strategy: validation

Validate before calling

fn validate_arity(args: &[&OsStr]) -> Result<(), &'static str> {
    match args.len() {
        2 => Ok( ),
        n if n > 2 => {
            let last = std::path::Path::new(args.last().unwrap());
            if last.is_dir() { Ok( ) } else { Err("multiple sources require a directory destination") }
        }
        _ => Err("need source and destination"),
    }
}

Try / catch

match ln(&host, args) {
    Err(e) if e.to_string().starts_with("extra operand") => eprintln!("pass at most SOURCE DEST, or end with an existing directory"),
    other => other?,
}

Prevention

When it happens

Trigger: Calling ln with three or more path arguments without a directory destination, e.g. `ln a b c`.

Common situations: Scripts that join many files into one ln call expecting GNU's 'link all into directory' mode while the last argument is not a directory; typo'd extra path.

Related errors


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

Appendix: source

Thrown at crates/pi-builtins/src/ln.rs:65

	Interactive,
	Force,
}

#[derive(Error, Debug)]
enum LnError {
	#[error("target {} is not a directory", _0.quote())]
	TargetIsNotADirectory(PathBuf),

	#[error("")]
	SomeLinksFailed,

	#[error("{} and {} are the same file", _0.quote(), _1.quote())]
	SameFile(PathBuf, PathBuf),

	#[error("missing destination file operand after {}", _0.quote())]
	MissingDestination(PathBuf),

	#[error("extra operand {}\nTry '{} --help' for more information.", _0.quote(), _1)]
	ExtraOperand(OsString, String),

	#[error("{}: hard link not allowed for directory", _0.to_string_lossy())]
	FailedToCreateHardLinkDir(PathBuf),

	#[error("{0}")]
	Message(String),

	#[error("{0}")]
	Io(#[from] std::io::Error),
}


mod options {
	pub const FORCE: &str = "force";
	//pub const DIRECTORY: &str = "directory";
	pub const INTERACTIVE: &str = "interactive";
	pub const NO_DEREFERENCE: &str = "no-dereference";

View on GitHub (pinned to 9690622007)