sxyazi/yazi · error · io::Error

trash info has no Path

Error message

trash info has no Path

What it means

`parse_original` (trash_info.rs:55) scans lines after the header until it finds one starting with `Path=`; hitting EOF first means the file has no put-back path at all, so it fails with `ErrorKind::InvalidData`, `trash info has no Path`. The key is required by the freedesktop trash spec.

Source

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

		}

		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 {
				return Err(io::Error::new(io::ErrorKind::InvalidData, "trash info has no Path"));
			}

			Self::trim_line(&mut line);
			let Some(value) = line.strip_prefix(b"Path=") else { continue };
			let decoded: Cow<[u8]> = percent_decode(value).into();

			let path = Path::new(OsStr::from_bytes(decoded.as_ref()));
			if path.as_os_str().is_empty() || !path.is_absolute() && path.has_parent_component() {
				return Err(io::Error::new(io::ErrorKind::InvalidData, "invalid original trash path"));
			}

			return Ok(if path.is_absolute() {
				path.to_owned()
			} else {
				Self::mount_point(root)?.join(path)
			});
		}
	}

View on GitHub (pinned to 94abcfa92f)

Solutions

  1. Add a valid `Path=<absolute-original-path>` line to the file and retry the restore.
  2. If the original location is unknown, remove the `.trashinfo` and manually salvage the backing file from `<root>/files/`.
  3. Report/fix whichever tool produced header-only trashinfo files.

Example fix

# before
[Trash Info]
DeletionDate=2026-01-01T00:00:00

# after
[Trash Info]
Path=/home/alice/report.pdf
DeletionDate=2026-01-01T00:00:00
Defensive patterns

Strategy: try-catch

Validate before calling

fn has_path_line(p: &std::path::Path) -> std::io::Result<bool> {
    use std::io::BufRead;
    let mut r = std::io::BufReader::new(std::fs::File::open(p)?);
    let mut line = Vec::new();
    r.read_until(b'\n', &mut line)?; // header
    loop {
        line.clear();
        if r.read_until(b'\n', &mut line)? == 0 { return Ok(false); }
        while matches!(line.last(), Some(b'\n' | b'\r')) { line.pop(); }
        if line.starts_with(b"Path=") { return Ok(true); }
    }
}

Try / catch

match trash.entry(&id) {
    Ok(e) => { /* ... */ }
    Err(e) if e.kind() == io::ErrorKind::InvalidData => {
        // missing Path= line: add `Path=/abs/original` to the .trashinfo, or purge the item
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: A `.trashinfo` containing only the `[Trash Info]` header, or with keys like `DeletionDate=` but no `Path=` line; files truncated mid-write.

Common situations: A crash or full disk while the trash implementation was writing metadata; trash info generated by buggy third-party tools.

Related errors


AI-assisted analysis of sxyazi/yazi@94abcfa92f (2026-08-16). Data as JSON: /api/errors/c7a808516fe1a677. Report an issue: GitHub.