can1357/oh-my-pi · error · HeadError
error reading {}: {}
Error message
error reading {}: {} What it means
HeadError::Io wraps any io::Error encountered while reading an input file during the head builtin's execution, formatting it as 'error reading <name>: <err>' with the path shell-quoted. It surfaces underlying OS-level read failures (file not found, permission denied, etc.) with the offending file's name attached.
Source
Thrown at crates/pi-builtins/src/head.rs:987
#[test]
fn test_more_lines() {
let input_reader = std::io::Cursor::new("a\nb\nc\n");
let output_reader = BufReader::new(take_lines(input_reader, 4, b'\n'));
let mut iter = output_reader.lines().map(|l| l.unwrap());
assert_eq!(Some(String::from("a")), iter.next());
assert_eq!(Some(String::from("b")), iter.next());
assert_eq!(Some(String::from("c")), iter.next());
assert_eq!(None, iter.next());
}
}
}
use take::{copy_all_but_n_bytes, copy_all_but_n_lines, take_lines};
#[derive(Error, Debug)]
enum HeadError {
/// Wrapper around `io::Error`
#[error("error reading {}: {}", name.quote(), err)]
Io { name: PathBuf, err: io::Error },
#[error("{0}")]
ParseError(String),
#[error("number of -bytes or -lines is too large")]
NumTooLarge(#[from] TryFromIntError),
#[error("{0}")]
MatchOption(String),
}
type HeadResult<T> = Result<T, HeadError>;
#[derive(Debug, PartialEq)]
enum Mode {
FirstLines(u64),View on GitHub (pinned to 9690622007)
Solutions
- Verify the file path exists and is spelled correctly (ls the directory)
- Check read permissions on the file (ls -l) and adjust with chmod/chown as appropriate
- Inspect the wrapped inner err message for the precise OS-level cause
- Handle the error variant in your caller to report or skip unreadable files gracefully
Example fix
// before
head("/var/log/missing.log", 10);
// after
let path = PathBuf::from("/var/log/app.log");
if path.exists() { head(&path, 10); } Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check before invoking head
if !std::path::Path::new(path).is_file() {
eprintln!("cannot read {path}: not a readable file");
} Try / catch
match head_result {
Err(HeadError::Io { name, err }) => eprintln!("skipping {}: {err}", name.display()),
Err(other) => return Err(other),
Ok(v) => /* ... */,
} Prevention
- Check path existence and permissions before passing files to head
- Expand and normalize paths (avoid dangling symlinks) in scripts
- Wrap shared-file reads with retry/backoff if files may be transiently locked
When it happens
Trigger: Calling the head builtin with a path that does not exist, lacks read permission, or where the underlying reader returns an I/O error mid-read (e.g. device errors, broken pipes on special files).
Common situations: Typos in file paths; reading files owned by another user; operating on dangling symlinks; passing directories where files are expected; network/special files that error during read.
Related errors
- error writing 'standard output': {err}
- 2
- Too many levels of symbolic links
- {}: {error}
- failed to create a unique fc temporary file
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/89b0e502545f6a7e.
Report an issue: GitHub.