sxyazi/yazi · error

invalid trash info path

Error message

invalid trash info path

What it means

TrashInfo::parse expects a path to a freedesktop .trashinfo file (e.g. .../info/cat.jpg.trashinfo). It first checks that the extension is exactly "trashinfo" and returns InvalidData "invalid trash info path" otherwise, then derives the trash root by expecting the parent directory to be named "info". Passing anything but a proper trashinfo file path fails here.

Solutions

  1. Pass the path inside the trash's info/ directory that ends with .trashinfo, not the files/ entry.
  2. Filter directory listings with extension == "trashinfo" before calling parse.
  3. Derive ids through the trash provider's listing APIs (tops/list) instead of hand-building paths.

Example fix

// before
let info = TrashInfo::parse(&trash_dir.join("files").join("cat.jpg"))?;
// after
let info = TrashInfo::parse(&trash_dir.join("info").join("cat.jpg.trashinfo"))?;
Defensive patterns

Strategy: validation

Validate before calling

// Rust
fn is_trashinfo_path(p: &Path) -> bool {
    p.extension() == Some(std::ffi::OsStr::new("trashinfo")) && p.parent().is_some_and(|p| p.file_name() == Some(std::ffi::OsStr::new("info")))
}

Try / catch

match TrashInfo::parse(path) {
    Err(e) if e.to_string().contains("invalid trash info path") => continue, // not a trash record; skip
    other => other?,
}

Prevention

When it happens

Trigger: Calling TrashInfo::parse with a path lacking the .trashinfo extension; passing a files/ entry (the trashed data) instead of the info/ record; scanning a directory that mixes records and other files; ids pointing at info/ itself rather than a record inside it.

Common situations: Directory iteration that doesn't filter by extension before parsing; a user-created file inside info/ without the .trashinfo suffix being picked up by a scanner; mixing up files/ and info/ subdirectories of a freedesktop trash.

Related errors


AI-assisted analysis of sxyazi/yazi@a541adde4e (2026-09-02). Data as JSON: /api/errors/10a7a14300d8c29a. Report an issue: GitHub.

Appendix: source

Thrown at yazi-fs/src/trash/freedesktop/trash_info.rs:17

use std::{borrow::Cow, ffi::OsStr, fs::File, io::{self, BufRead, BufReader}, os::unix::ffi::OsStrExt, path::{Path, PathBuf}};

use percent_encoding::percent_decode;
use yazi_shim::{Uzers, path::PathExt};

pub(super) struct TrashInfo {
	pub(super) root:     PathBuf,
	pub(super) backing:  PathBuf,
	pub(super) original: PathBuf,
}

impl TrashInfo {
	// Parses from a trashinfo path, e.g.:
	//   /home/alice/.local/share/Trash/info/cat.jpg.trashinfo
	pub(super) fn parse(info: &Path) -> io::Result<Self> {
		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()
			.filter(|&stem| stem != OsStr::new(".") && stem != OsStr::new(".."))
			.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"));

View on GitHub (pinned to a541adde4e)