can1357/oh-my-pi · error
target directory {0}: Not a directory
Error message
target directory {0}: Not a directory What it means
This is MvError::TargetNotADirectory from crates/pi-builtins/src/mv.rs. Raised up front in `run_matches` (mv.rs:381-385) when the explicit `-t/--target-directory` option is given but the resolved DIRECTORY operand is not a directory on the filesystem. Unlike the implicit last-operand form (NotADirectory), this check runs before any source is examined, so it is the earliest and clearest signal that the `-t` target is invalid.
Source
Thrown at crates/pi-builtins/src/mv.rs:67
};
#[derive(Debug, Error)]
enum MvError {
#[error("cannot stat {0}: No such file or directory")]
NoSuchFile(String),
#[error("cannot stat {0}: Not a directory")]
CannotStatNotADirectory(String),
#[error("{0} and {1} are the same file")]
SameFile(String, String),
#[error("cannot move {0} to a subdirectory of itself, {1}")]
SelfTargetSubdirectory(String, String),
#[error("cannot overwrite directory {0} with non-directory")]
DirectoryToNonDirectory(String),
#[error("cannot overwrite non-directory {1} with directory {0}")]
NonDirectoryToDirectory(String, String),
#[error("target {0}: Not a directory")]
NotADirectory(String),
#[error("target directory {0}: Not a directory")]
TargetNotADirectory(String),
#[error("failed to access {0}: Not a directory")]
FailedToAccessNotADirectory(String),
}
#[derive(Debug, Error)]
enum MvFailure {
#[error(transparent)]
Move(#[from] MvError),
#[error(transparent)]
Io(#[from] io::Error),
#[error("{0}")]
Message(String),
}
type MvResult<T> = Result<T, MvFailure>;
/// Parsed `mv` invocation.View on GitHub (pinned to 9690622007)
Solutions
- Create the directory before invoking: `mkdir -p "$(target)"` then `mv -t "$target" sources...`.
- Double-check the value passed to -t; it must be an existing directory, not a destination filename.
- Verify mounts/variables that supply the path (`echo $target; ls -ld "$target"`).
- If you meant a single rename, drop `-t` and use `mv src dest`.
Example fix
// before (fails: $out is not an existing directory) mv -t "$out" *.log // after mkdir -p "$out" && mv -t "$out" *.log
Defensive patterns
Strategy: validation
Validate before calling
import * as fs from "node:fs/promises";
export async function resolveTargetDir(dir: string): Promise<string> {
const st = await fs.stat(dir).catch(() => null);
if (!st) await fs.mkdir(dir, { recursive: true });
else if (!st.isDirectory()) throw new Error(`-t target ${dir} exists but is not a directory`);
return dir;
}
// const t = await resolveTargetDir(target); mv -t t sources... Try / catch
try {
await runBuiltin("mv", ["-t", target, ...sources]);
} catch (e) {
if (String(e).startsWith("target directory ") && String(e).includes("Not a directory")) {
logger.error("--target-directory must be an existing directory", { target });
} else throw e;
} Prevention
- Validate the -t value with stat/isDirectory before constructing the command.
- mkdir -p the target when its existence depends on a previous step or mount.
- Don't confuse -t DIR (move into DIR) with the plain two-operand rename form.
- Echo or log the expanded variable supplying -t in scripts to catch empty/renamed paths early.
When it happens
Trigger: `mv -t somefile src1 src2` where somefile is a regular file or symlink-to-file; `mv --target-directory=does_not_exist src` (path never created); `-t` pointing at a deleted or renamed directory; scripts interpolating an empty or wrong variable into the -t value.
Common situations: Pipeline scripts where the target directory is produced by a previous command that failed silently; find/xargs-driven moves passing a stale directory path; users confusing `-t DIR` (move into DIR) with plain rename semantics; container images where the directory was expected from a mounted volume that failed to mount.
Related errors
- target {0}: Not a directory
- failed to create {} via template {}: No such file or directo
- cannot stat {0}: No such file or directory
- cannot stat {0}: Not a directory
- {0} and {1} are the same file
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/84036038f6565287.
Report an issue: GitHub.