can1357/oh-my-pi · error · CatError

Is a directory

Error message

Is a directory

What it means

`CatError::IsDirectory` reports that a `cat` argument is a directory, which cannot be read as a byte stream. It matches coreutils' behavior of printing `cat: dir: Is a directory` and continuing with other operands rather than using the raw EISDIR io::Error text. This keeps output consistent with POSIX cat.

Source

Thrown at crates/pi-builtins/src/cat.rs:78

	}

	fn write(&self, writer: &mut impl Write) -> io::Result<()> {
		writer.write_all(self.to_str())
	}
}

#[derive(Error, Debug)]
enum CatError {
	/// Wrapper around `io::Error`.
	#[error("{}", strip_errno(.0))]
	Io(io::Error),
	/// The downstream reader closed its pipe; this ends the copy quietly.
	#[error("broken pipe")]
	BrokenPipe,
	/// Unknown file type; it is not a regular file, socket, or known device.
	#[error("unknown filetype: {ft_debug}")]
	UnknownFiletype { ft_debug: String },
	#[error("Is a directory")]
	IsDirectory,
	#[cfg(unix)]
	#[error("No such device or address")]
	NoSuchDeviceOrAddress,
	#[error("Too many levels of symbolic links")]
	TooManySymlinks,
}

impl From<io::Error> for CatError {
	fn from(error: io::Error) -> Self {
		if error.kind() == ErrorKind::BrokenPipe {
			Self::BrokenPipe
		} else {
			Self::Io(error)
		}
	}
}

View on GitHub (pinned to 9690622007)

Solutions

  1. Remove the directory from the argument list; cat only regular files.
  2. If you wanted directory contents, use `cat dir/*` (with care for subdirectories) or `find dir -type f -exec cat {} +`.
  3. Tighten globs (e.g. `cat *.txt`) so directories are not matched.

Example fix

// before
$ cat src/
cat: src/: Is a directory
// after
$ cat src/*.rs
Defensive patterns

Strategy: validation

Validate before calling

// shell: filter out directories before passing operands to cat
files=()
for p in "$@"; do
  [ -f "$p" ] && files+=("$p")
done
cat -- "${files[@]}"

Try / catch

// shell: tolerate directory operands in bulk globs
for f in *; do
  [ -f "$f" ] && cat -- "$f" || true
done

Prevention

When it happens

Trigger: `cat somedir` where `metadata(path)` indicates a directory; the read path detects `FileType::is_dir()` (or maps EISDIR) and returns this variant.

Common situations: Glob patterns that expand to include directories (`cat *` in a dir with subdirs); scripts with a variable meant to hold a filename but holding a path; recursive expansions accidentally including directories.

Related errors


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