{"record":{"id":"19ef72c5bb09d066","repo":"can1357/oh-my-pi","slug":"read-error","errorCode":null,"errorMessage":"{}: read error: {}","messagePattern":"(.+?): read error: (.+?)","errorType":"error_code","errorClass":"TacError","httpStatus":null,"severity":"error","filePath":"crates/pi-builtins/src/tac.rs","lineNumber":36,"sourceCode":"use 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.\npub(crate) struct Tac {\n\tmatches: ArgMatches,\n}","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/crates/pi-builtins/src/tac.rs#L18-L54","documentation":"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.","triggerScenarios":"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.","commonSituations":"Network filesystems dropping connections; reading special files that return EIO; pipes from processes killed mid-write; hardware/storage errors.","solutions":["Inspect the upstream producer if reading a pipe: fix or restart the process feeding tac.","For files on network mounts, remount the filesystem or copy the file locally before reversing.","Retry the read; transient I/O errors often clear after the underlying service recovers.","Check disk/device health (`dmesg`, smartctl) if the error recurs on local storage."],"exampleFix":"// before: reading from flaky NFS\ntac /mnt/nfs/big.log  // read error: Input/output error\n\n// after\ncp /mnt/nfs/big.log /tmp/big.log && tac /tmp/big.log","handlingStrategy":"retry","validationCode":null,"typeGuard":"function isReadError(err) {\n  return err instanceof Error && /: read error: /.test(err.message);\n}","tryCatchPattern":"try {\n  await tac.run([file]);\n} catch (err) {\n  if (/: read error: /.test(String(err))) {\n    await Bun.sleep(500);\n    return tac.run([file]); // retry once after transient I/O failure\n  } else throw err;\n}","preventionTips":["Copy files from network mounts locally before heavy reads.","Keep upstream pipe producers alive until consumers finish.","Monitor storage health; treat recurring read errors as hardware/service issues."],"tags":["io","tac","read-error","stdin"],"backgroundTag":"io-read-error","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}