can1357/oh-my-pi · error · LnError
2
2
Error message
target {} is not a directory What it means
LnError::TargetIsNotADirectory is thrown by the ln builtin when link creation is requested inside a target path that exists but is not a directory — i.e., the caller asked for links to be placed in a directory (form `ln source... target-dir/`) but the target is a regular file or other non-directory. It carries the offending PathBuf, shell-quoted in the message, and surfaces with OS error code 2 (InvalidInput-class io error).
Source
Thrown at crates/pi-builtins/src/ln.rs:53
symbolic: bool,
relative: bool,
logical: bool,
target_dir: Option<PathBuf>,
no_target_dir: bool,
no_dereference: bool,
verbose: bool,
}
#[derive(Clone, Debug, Eq, PartialEq)]
enum OverwriteMode {
NoClobber,
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}")]View on GitHub (pinned to 9690622007)
Solutions
- Verify the target path is a directory (ls -ld target) or create it with mkdir -p before linking
- Remove or rename the non-directory file occupying the target path
- Pass a single source when creating a named link instead of the directory-target form
- If the path is a symlink, ensure it resolves to a directory
Example fix
// before
ln(["a.txt", "b.txt", "dest"], {}); // dest is a regular file
// after
fs::create_dir_all("dest");
ln(["a.txt", "b.txt", "dest"], {}); Defensive patterns
Strategy: validation
Validate before calling
fn ensure_dir_target(target: &std::path::Path) -> std::io::Result<()> {
let md = std::fs::metadata(target)?;
if !md.is_dir() {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
format!("{} is not a directory", target.display()),
));
}
Ok(())
} Try / catch
match ln_result {
Err(e) if e.to_string().contains("is not a directory") => {
eprintln!("create or fix the target directory first: {e}");
}
Err(e) => return Err(e),
Ok(()) => /* ... */,
} Prevention
- Check metadata().is_dir() on multi-source link targets before invoking ln
- mkdir -p the target directory in setup steps of scripts
- Distinguish single-source named-link form from multi-source directory-target form in your call sites
When it happens
Trigger: Calling the ln builtin with multiple sources and a final target argument that resolves to an existing non-directory file (e.g. `ln a b c existing-file` expecting 'existing-file' to be a directory); creating a hard/symbolic link where the destination directory component is actually a file.
Common situations: Typos where the intended directory name collides with an existing file name; scripts assuming a directory exists but a file was created there earlier; passing a symlink to a file as the target directory.
Related errors
- Too many levels of symbolic links
- {}: {error}
- failed to create a unique fc temporary file
- error reading {}: {}
- error writing 'standard output': {err}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/d377dcd0886b4ba9.
Report an issue: GitHub.