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

  1. Verify the file path exists and is spelled correctly (ls the directory)
  2. Check read permissions on the file (ls -l) and adjust with chmod/chown as appropriate
  3. Inspect the wrapped inner err message for the precise OS-level cause
  4. 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

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


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