can1357/oh-my-pi · error · TacError

{}: read error: {}

Error message

{}: read error: {}

What it means

This tac builtin error (crates/pi-builtins/src/tac.rs, Read) means an I/O error occurred while reading the contents of an input file or stdin after it was successfully opened. The operand name (quoted with maybe_quote) and the errno-stripped message are included. Unlike Open, the path was reachable; the read itself failed mid-stream.

Source

Thrown at crates/pi-builtins/src/tac.rs:36

use crate::host::{Host, Utility, format_usage, matches_parser, util};

mod options {
	pub static BEFORE: &str = "before";
	pub static REGEX: &str = "regex";
	pub static SEPARATOR: &str = "separator";
	pub static FILE: &str = "file";
}

#[derive(Debug, Error)]
enum TacError {
	/// A regular expression given by the user is invalid.
	#[error("invalid regular expression: {0}")]
	InvalidRegex(regex::Error),
	/// An error opening a file for reading.
	#[error("failed to open {} for reading: {}", .0.quote(), strip_errno(.1))]
	Open(OsString, std::io::Error),
	/// An error reading the contents of a file or stdin.
	#[error("{}: read error: {}", .0.maybe_quote(), strip_errno(.1))]
	Read(OsString, std::io::Error),
	/// An error writing the reversed contents of a file or stdin.
	#[error("failed to write to stdout: {}", strip_errno(.0))]
	Write(std::io::Error),
}

fn strip_errno(error: &std::io::Error) -> String {
	let mut message = error.to_string();
	if let Some(position) = message.find(" (os error ") {
		message.truncate(position);
	}
	message
}

/// Parsed `tac` invocation.
pub(crate) struct Tac {
	matches: ArgMatches,
}

View on GitHub (pinned to 9690622007)

Solutions

  1. Inspect the upstream producer if reading a pipe: fix or restart the process feeding tac.
  2. For files on network mounts, remount the filesystem or copy the file locally before reversing.
  3. Retry the read; transient I/O errors often clear after the underlying service recovers.
  4. Check disk/device health (`dmesg`, smartctl) if the error recurs on local storage.

Example fix

// before: reading from flaky NFS
tac /mnt/nfs/big.log  // read error: Input/output error

// after
cp /mnt/nfs/big.log /tmp/big.log && tac /tmp/big.log
Defensive patterns

Strategy: retry

Type guard

function isReadError(err) {
  return err instanceof Error && /: read error: /.test(err.message);
}

Try / catch

try {
  await tac.run([file]);
} catch (err) {
  if (/: read error: /.test(String(err))) {
    await Bun.sleep(500);
    return tac.run([file]); // retry once after transient I/O failure
  } else throw err;
}

Prevention

When it happens

Trigger: Reading from a file on a failing/stale mount (NFS I/O error), a device that errors on read, or stdin connected to a process/socket that terminated, e.g. `tac /dev/baddevice`, `someproc | tac` when someproc crashes.

Common situations: Network filesystems dropping connections; reading special files that return EIO; pipes from processes killed mid-write; hardware/storage errors.

Related errors


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