can1357/oh-my-pi · error · WcError
{context}: {source}
Error message
{context}: {source} What it means
WcError::Io { context, source } is wc's contextual IO error: it prefixes an io::Error with what wc was doing (`{context}: {source}`) and keeps the original as #[source]. The context tells you which phase failed (opening, reading, or stat-ing a file) while the source carries the errno-level cause.
Source
Thrown at crates/pi-builtins/src/wc.rs:793
match self {
Self::Auto => num_inputs > 1,
Self::Always | Self::Only => true,
Self::Never => false,
}
}
}
#[derive(Debug, Error)]
enum WcError {
#[error("extra operand {}\nfile operands cannot be combined with --files0-from", extra.quote())]
FilesDisabled { extra: Cow<'static, OsStr> },
#[error("when reading file names from standard input, no file name of '-' allowed")]
StdinReprNotAllowed,
#[error("invalid zero-length file name")]
ZeroLengthFileName,
#[error("{path}:{idx}: invalid zero-length file name")]
ZeroLengthFileNameCtx { path: Cow<'static, str>, idx: usize },
#[error("{context}: {source}")]
Io {
context: String,
#[source]
source: io::Error,
},
}
impl WcError {
fn zero_len(ctx: Option<(&Input, usize)>) -> Self {
match ctx {
Some((input, idx)) => {
let path = match input {
Input::Stdin(_) => STDIN_REPR.into(),
Input::Path(path) => escape_name_wrapper(path.as_os_str()).into(),
};
Self::ZeroLengthFileNameCtx { path, idx }
},
None => Self::ZeroLengthFileName,View on GitHub (pinned to 9690622007)
Solutions
- Read `context` to see which file/operation failed, then the `source` errno for the cause
- Check existence and permissions of the reported path (ls -l, or run as a user with access)
- Skip unreadable inputs and continue with the remaining files in the list
- For ENOENT, correct the path or regenerate the file list from a current find/ls
Example fix
// context: "a.log: read" source: Permission denied (os error 13)
// after
for f in files {
if let Err(e) = std::fs::File::open(f) {
if e.kind() == std::io::ErrorKind::PermissionDenied {
eprintln!("skipping unreadable: {f}");
continue;
}
return Err(e.into());
}
// process f
} Defensive patterns
Strategy: try-catch
Validate before calling
fn wc_inputs_ok(paths: &[std::path::PathBuf]) -> Vec<(std::path::PathBuf, std::io::Error)> {
paths.iter()
.filter_map(|p| std::fs::File::open(p).err().map(|e| (p.clone(), e)))
.collect()
} Try / catch
match result {
Err(WcError::Io { context, source }) => {
eprintln!("{context}: {source}");
if source.kind() == std::io::ErrorKind::NotFound {
// regenerate or drop the missing input
} else if source.kind() == std::io::ErrorKind::PermissionDenied {
// skip and continue with remaining files
}
}
other => other.map(|_| ()),
} Prevention
- Pre-open (or stat) every input path before batch processing to fail fast on bad ones
- Inspect source.kind()/raw_os_error() rather than parsing the Display string
- Skip-and-log unreadable files instead of aborting the whole list
- Regenerate file lists right before use to avoid stale (deleted) entries
When it happens
Trigger: Any io::Error during wc's per-file processing — open() failing with EACCES/ENOENT, read() failing mid-stream, or metadata() failing — wrapped with the file-specific context string.
Common situations: wc on a nonexistent or misspelled path (ENOENT); unreadable files under another user (EACCES); reading special files with unusual semantics; disk/device errors on large inputs.
Related errors
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/f182d32acbe404e6.
Report an issue: GitHub.