can1357/oh-my-pi · warning · LsError
{}: not listing already-listed directory
Error message
{}: not listing already-listed directory What it means
LsError::AlreadyListedError is raised by the builtin `ls` when it encounters a directory argument that has already been listed earlier in the same invocation. GNU-compatible ls deliberately skips duplicate directory arguments to avoid printing the same listing twice (unless -H/--deref-command-line or similar semantics apply).
Source
Thrown at crates/pi-builtins/src/ls.rs:3708
} else {
format!("cannot open file {}: Permission denied", .0.quote())
},
},
_ => if 9 == .1.raw_os_error().unwrap_or(1) {
format!("cannot open directory {}: Bad file descriptor", .0.quote())
} else {
format!("unknown io error: {}, '{:?}'", .0.quote(), .1)
},
})]
IOErrorContext(PathBuf, std::io::Error, bool, bool),
#[error("invalid --block-size argument '{0}'")]
BlockSizeParseError(String),
#[error("--dired and --zero are incompatible")]
DiredAndZeroAreIncompatible,
#[error("{}: not listing already-listed directory", .0.maybe_quote())]
AlreadyListedError(PathBuf),
#[error("invalid --time-style argument {}\nPossible values are:\n - [posix-]full-iso\n - [posix-]long-iso\n - [posix-]iso\n - [posix-]locale\n - +FORMAT (e.g., +%H:%M) for a 'date'-style format\n\nFor more information try --help", .0.quote())]
TimeStyleParseError(String),
}
impl LsError {
fn code(&self) -> i32 {
match self {
Self::InvalidLineWidth(_) => 2,
Self::IOError(_) => 1,
Self::IOErrorContext(_, _, false, _) => 1,
Self::IOErrorContext(_, _, true, _) => 2,
Self::BlockSizeParseError(_) => 2,
Self::DiredAndZeroAreIncompatible => 2,
Self::AlreadyListedError(_) => 2,
Self::TimeStyleParseError(_) => 2,
}View on GitHub (pinned to 9690622007)
Solutions
- Remove the duplicate directory argument from the command line
- Deduplicate paths in the script before invoking ls (e.g. `printf '%s\n' "$@" | awk '!seen[$0]++'`)
- If repeated listing is genuinely wanted, list them in separate ls invocations
- Quote globs carefully so they don't expand to overlapping paths
Example fix
// before ls src src // after ls src
Defensive patterns
Strategy: validation
Validate before calling
const dirs = [...new Set(rawDirs.map(d => resolve(d)))];
if (dirs.length !== rawDirs.length) {
console.warn('duplicate directory arguments removed');
} Type guard
const hasDuplicatePaths = (paths: string[]): boolean => new Set(paths.map(p => resolve(p))).size !== paths.length;
Try / catch
try {
runLs(dirs);
} catch (e) {
if (String(e).includes('not listing already-listed directory')) {
runLs([...new Set(dirs)]); // dedupe and continue
} else throw e;
} Prevention
- Deduplicate directory lists before invoking ls
- Expand globs into a Set before building the command
- Avoid repeating paths 'for emphasis' — ls skips them
- Deduplicate by resolved path, not raw string, to catch ./dir vs dir
When it happens
Trigger: Passing the same directory twice on the command line, e.g. `ls dir dir`, or `ls . ./` when both resolve to the same directory already listed.
Common situations: Shell globs expanding to duplicates (e.g. `ls dir dir/*` where dir matches again), build scripts concatenating directory lists that contain repeats, users repeating a path for emphasis expecting a second listing.
Related errors
- 2
- invalid --block-size argument '{0}'
- --dired and --zero are incompatible
- invalid --time-style argument {} Possible values are: - [p
- --list-details, --exec, and --exec-batch are not supported b
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/f4cd5e8505395b48.
Report an issue: GitHub.