can1357/oh-my-pi · error · TouchError
failed to get attributes of {}: {}
Error message
failed to get attributes of {}: {} What it means
TouchError::ReferenceFileInaccessible is raised when `touch -r <reference>` cannot stat the reference file whose timestamps should be copied. The library needs the reference's atime/mtime via metadata() and wraps the io::Error with the quoted path. It mirrors GNU coreutils' 'failed to get attributes of' diagnostics.
Source
Thrown at crates/pi-builtins/src/touch.rs:45
use rustix::fs::Timestamps;
#[cfg(unix)]
use rustix::fs::futimens;
#[cfg(target_os = "linux")]
use uucore::libc;
use uucore::{display::Quotable, parser::shortcut_value_parser::ShortcutValueParser};
use brush_core::{ShellExtensions, builtins::Registration};
use thiserror::Error as ThisError;
use crate::host::{Host, Utility, format_usage, matches_parser, util};
#[derive(Debug, ThisError)]
enum TouchError {
#[error("Unable to parse date: {0}")]
InvalidDateFormat(String),
#[error("Source has invalid access or modification time: {0}")]
InvalidFiletime(FileTime),
#[error("failed to get attributes of {}: {}", .0.quote(), io_error(.1))]
ReferenceFileInaccessible(PathBuf, std::io::Error),
#[cfg(windows)]
#[error("GetFinalPathNameByHandleW failed with code {0}")]
WindowsStdoutPathError(String),
#[error("{0}")]
Message(String),
}
fn io_error(error: &std::io::Error) -> String {
if error.raw_os_error().is_some() {
match error.kind() {
ErrorKind::NotFound => "No such file or directory".into(),
ErrorKind::PermissionDenied => "Permission denied".into(),
ErrorKind::AlreadyExists => "Already exists".into(),
ErrorKind::WouldBlock => "Would block".into(),
_ => error.to_string().split(" (os error ").next().unwrap_or_default().into(),
}
} else {View on GitHub (pinned to 9690622007)
Solutions
- Verify the reference file exists and its parent directory grants you search (execute) permission
- Re-run with the correct path or create the reference file first
- If you only need fixed timestamps, use -d/-t with an explicit date instead of -r
- Check quoting of the path (spaces/special characters) in your shell invocation
Example fix
// before: touch -r missing_ref.txt target.txt -> fails
// after
let ref_path = "missing_ref.txt";
if !std::path::Path::new(ref_path).exists() {
// fall back to an explicit date
// touch -d "2026-01-01 00:00" target.txt
} Defensive patterns
Strategy: validation
Validate before calling
fn validate_reference(path: &std::path::Path) -> Result<(), String> {
match std::fs::metadata(path) {
Ok(_) => Ok(()),
Err(e) => Err(format!("reference '{}' inaccessible: {}", path.display(), e)),
}
} Try / catch
match result {
Err(TouchError::ReferenceFileInaccessible(path, io)) => {
eprintln!("reference {} failed: {} — falling back to explicit date", path.display(), io);
// proceed with -d explicit timestamp
}
other => other.map(|_| ()),
} Prevention
- Always stat the -r reference path before invoking touch
- Use absolute paths for reference files in scripts
- Prefer -d/-t explicit dates when the reference may be ephemeral
- Quote paths with spaces in shell wrappers
When it happens
Trigger: Calling touch with `-r/--reference=FILE` where FILE does not exist, lacks read permission on its directory, or the path is otherwise unstat-able (broken symlink target, permission denied).
Common situations: Copy-pasting a reference path with a typo; referencing a file in another user's directory; the reference file was deleted between listing and touching; running without sufficient privileges (e.g. in restricted CI containers).
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/aa1f5c6939815a09.
Report an issue: GitHub.