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
- Check the file exists at the given path (`ls -l <file>`) and fix any typo.
- Verify read permission (`test -r <file>`) and chmod or use an account with access.
- If the operand should be stdin, pass '-' explicitly instead of a path.
- 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
- Verify existence and readability of each operand before invoking tac.
- Expand globs freshly at call time to avoid reading deleted files.
- Use '-' when input should come from stdin.
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
- {}: read error: {}
- failed to write to stdout: {}
- Computed edit range is out of bounds
- I/O error occurred
- {}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/ffc063f83d3ece31.
Report an issue: GitHub.