sxyazi/yazi · error · io::Error
invalid original trash path
Error message
invalid original trash path
What it means
After parsing the `Path=` value, `TrashInfo::parse` (trash_info.rs:36) sanity-checks the resulting original path: it must have a file name. Paths like `/`, `..`, or anything ending in a parent component have no terminal file name and are rejected with `ErrorKind::InvalidData`, `invalid original trash path`, because no file could ever be restored there.
Source
Thrown at yazi-fs/src/trash/freedesktop/trash_info.rs:36
if info.extension() != Some(OsStr::new("trashinfo")) {
return Err(io::Error::new(io::ErrorKind::InvalidData, "invalid trash info path"));
}
// /home/alice/.local/share/Trash
let root = info
.parent()
.filter(|p| p.file_name() == Some(OsStr::new("info")))
.and_then(Path::parent)
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "invalid trash info path"))?;
// cat.jpg
let stem = info
.file_stem()
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "invalid trash info path"))?;
let original = Self::parse_original(info, root)?;
if original.file_name().is_none() {
return Err(io::Error::new(io::ErrorKind::InvalidData, "invalid original trash path"));
}
Ok(Self { root: root.to_owned(), backing: root.join("files").join(stem), original })
}
fn parse_original(info: &Path, root: &Path) -> io::Result<PathBuf> {
let mut reader = BufReader::new(File::open(info)?);
let mut line = Vec::new();
reader.read_until(b'\n', &mut line)?;
Self::trim_line(&mut line);
if line != b"[Trash Info]" {
return Err(io::Error::new(io::ErrorKind::InvalidData, "invalid trash info header"));
}
loop {
line.clear();
if reader.read_until(b'\n', &mut line)? == 0 {View on GitHub (pinned to 94abcfa92f)
Solutions
- Edit the `.trashinfo` and set `Path=` to the real absolute original location (e.g. `Path=/home/alice/report.pdf`).
- Delete the broken `.trashinfo` (and its orphaned backing file in `files/`) if the original location is unknown.
- If you generate trash metadata, always write absolute paths with a final component.
Example fix
# before (~/.local/share/Trash/info/x.trashinfo) [Trash Info] Path=/ # after [Trash Info] Path=/home/alice/report.pdf
Defensive patterns
Strategy: validation
Validate before calling
// after reading Path= yourself, sanity-check before relying on it:
let decoded: std::path::PathBuf = /* percent-decoded Path= value */;
if decoded.file_name().is_none() {
// original location is unusable ("/", ".."); skip or repair the .trashinfo
} Type guard
fn has_terminal_file_name(p: &std::path::Path) -> bool {
p.file_name().is_some_and(|n| !n.is_empty())
} Try / catch
match trash.entry(&id) {
Ok(e) => { /* ... */ }
Err(e) if e.kind() == io::ErrorKind::InvalidData => { /* Path= is "/" or "..": edit or delete the .trashinfo */ }
Err(e) => return Err(e),
} Prevention
- When writing .trashinfo files, always store the absolute original path.
- Treat Path=/ or Path=.. entries as corrupt; repair or purge them.
- Validate any hand-edited trash metadata with a file_name check before restore.
When it happens
Trigger: A `.trashinfo` whose `Path=` value decodes to `/` or `..` (or `foo/..`); hand-edited or maliciously crafted trash metadata.
Common situations: Corrupted metadata after partial writes; trash info written by non-conformant tools; users editing `.trashinfo` files by hand.
Related errors
- invalid trash info path
- invalid trash info header
- trash info has no Path
- invalid trash mount point
- invalid trash item path
AI-assisted analysis of sxyazi/yazi@94abcfa92f (2026-08-16).
Data as JSON: /api/errors/998349e4b4f54bf4.
Report an issue: GitHub.