{"record":{"id":"ffc063f83d3ece31","repo":"can1357/oh-my-pi","slug":"failed-to-open-for-reading","errorCode":null,"errorMessage":"failed to open {} for reading: {}","messagePattern":"failed to open (.+?) for reading: (.+?)","errorType":"error_code","errorClass":"TacError","httpStatus":null,"severity":"error","filePath":"crates/pi-builtins/src/tac.rs","lineNumber":33,"sourceCode":"use thiserror::Error;\nuse uucore::display::Quotable;\n\nuse crate::host::{Host, Utility, format_usage, matches_parser, util};\n\nmod options {\n\tpub static BEFORE: &str = \"before\";\n\tpub static REGEX: &str = \"regex\";\n\tpub static SEPARATOR: &str = \"separator\";\n\tpub static FILE: &str = \"file\";\n}\n\n#[derive(Debug, Error)]\nenum TacError {\n\t/// A regular expression given by the user is invalid.\n\t#[error(\"invalid regular expression: {0}\")]\n\tInvalidRegex(regex::Error),\n\t/// An error opening a file for reading.\n\t#[error(\"failed to open {} for reading: {}\", .0.quote(), strip_errno(.1))]\n\tOpen(OsString, std::io::Error),\n\t/// An error reading the contents of a file or stdin.\n\t#[error(\"{}: read error: {}\", .0.maybe_quote(), strip_errno(.1))]\n\tRead(OsString, std::io::Error),\n\t/// An error writing the reversed contents of a file or stdin.\n\t#[error(\"failed to write to stdout: {}\", strip_errno(.0))]\n\tWrite(std::io::Error),\n}\n\nfn strip_errno(error: &std::io::Error) -> String {\n\tlet mut message = error.to_string();\n\tif let Some(position) = message.find(\" (os error \") {\n\t\tmessage.truncate(position);\n\t}\n\tmessage\n}\n\n/// Parsed `tac` invocation.","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/crates/pi-builtins/src/tac.rs#L15-L51","documentation":"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`.","triggerScenarios":"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`.","commonSituations":"Typos or stale paths in scripts; files deleted between globbing and reading; permission-restricted files; running in a container without the file mounted.","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."],"exampleFix":"// before\ntac /var/log/app.log.9  // failed to open for reading: No such file or directory\n\n// after\ntac $(ls /var/log/app.log.* | tail -1)","handlingStrategy":"validation","validationCode":"import { accessSync, constants, statSync } from 'node:fs';\nfunction readableFile(p) {\n  try {\n    accessSync(p, constants.R_OK);\n    return statSync(p).isFile();\n  } catch { return false; }\n}","typeGuard":"function isOpenError(err) {\n  return err instanceof Error && /^failed to open .+ for reading:/.test(err.message);\n}","tryCatchPattern":"try {\n  await tac.run([file]);\n} catch (err) {\n  if (/^failed to open .+ for reading:/.test(String(err))) {\n    console.error(`input ${file} missing or unreadable; skipping`);\n  } else throw err;\n}","preventionTips":["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."],"tags":["io","tac","file-open","enoent"],"backgroundTag":"file-open-failed","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}