can1357/oh-my-pi · error · TacError

failed to open {} for reading: {}

Error message

failed to open {} for reading: {}

What it means

This tac builtin error (crates/pi-builtins/src/tac.rs, Open) means a file given as an input operand could not be opened for reading. The message includes the quoted file name and an errno-stripped io::Error description. It mirrors GNU tac's `tac: failed to open 'x' for reading: No such file or directory`.

Source

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

use thiserror::Error;
use uucore::display::Quotable;

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.

View on GitHub (pinned to 9690622007)

Solutions

  1. Check the file exists at the given path (`ls -l <file>`) and fix any typo.
  2. Verify read permission (`test -r <file>`) and chmod or use an account with access.
  3. If the operand should be stdin, pass '-' explicitly instead of a path.
  4. Handle ENOENT in the calling script so missing optional inputs are skipped gracefully.

Example fix

// before
tac /var/log/app.log.9  // failed to open for reading: No such file or directory

// after
tac $(ls /var/log/app.log.* | tail -1)
Defensive patterns

Strategy: validation

Validate before calling

import { accessSync, constants, statSync } from 'node:fs';
function readableFile(p) {
  try {
    accessSync(p, constants.R_OK);
    return statSync(p).isFile();
  } catch { return false; }
}

Type guard

function isOpenError(err) {
  return err instanceof Error && /^failed to open .+ for reading:/.test(err.message);
}

Try / catch

try {
  await tac.run([file]);
} catch (err) {
  if (/^failed to open .+ for reading:/.test(String(err))) {
    console.error(`input ${file} missing or unreadable; skipping`);
  } else throw err;
}

Prevention

When it happens

Trigger: Passing a nonexistent path, a directory (on platforms where opening a directory for read fails), or a file without read permission to tac: `tac missing.txt`, `tac /root/secret`.

Common situations: Typos or stale paths in scripts; files deleted between globbing and reading; permission-restricted files; running in a container without the file mounted.

Related errors


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