sxyazi/yazi · error · io::Error
invalid trash info header
Error message
invalid trash info header
What it means
`TrashInfo::parse_original` (trash_info.rs:49) reads the first line of the `.trashinfo` file and requires it to be exactly `[Trash Info]` (after trimming trailing CR/LF). Any other first line — a different header, a BOM, garbage bytes — yields `ErrorKind::InvalidData`, `invalid trash info header`.
Source
Thrown at yazi-fs/src/trash/freedesktop/trash_info.rs:49
.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 {
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() {View on GitHub (pinned to 94abcfa92f)
Solutions
- Fix the file: make line 1 exactly `[Trash Info]`, with no leading BOM or whitespace.
- If the file is junk, delete it together with its backing entry in `files/`.
- Regenerate the `.trashinfo` with correct `Path=`/`DeletionDate=` if you know the original location.
Example fix
# before (hex: EF BB BF 5B ... = BOM before header) [Trash Info] Path=/home/alice/cat.jpg # after [Trash Info] Path=/home/alice/cat.jpg
Defensive patterns
Strategy: try-catch
Validate before calling
// quick pre-check when operating on .trashinfo files directly:
fn has_valid_header(p: &std::path::Path) -> std::io::Result<bool> {
use std::io::BufRead;
let mut line = Vec::new();
std::io::BufReader::new(std::fs::File::open(p)?).read_until(b'\n', &mut line)?;
while matches!(line.last(), Some(b'\n' | b'\r')) { line.pop(); }
Ok(line == b"[Trash Info]")
} Try / catch
match trash.entry(&id) {
Ok(e) => { /* ... */ }
Err(e) if e.kind() == io::ErrorKind::InvalidData => {
// header corrupted: rewrite line 1 as exactly "[Trash Info]" (no BOM), or delete the file
}
Err(e) => return Err(e),
} Prevention
- Save .trashinfo files as plain ASCII/UTF-8 without BOM.
- Keep line 1 exactly `[Trash Info]` when editing metadata.
- Treat InvalidData from entry() as on-disk corruption; repair or purge, don't retry blindly.
When it happens
Trigger: Opening (via `Trash::entry`) a `.trashinfo` whose first line is not the INI section header: text editors saving with a UTF-8 BOM, files truncated at the top, or non-trash files merely named `*.trashinfo`.
Common situations: Hand-edited metadata saved by editors that add BOMs or re-encode; partially overwritten files after a crash; a random file renamed to `.trashinfo`.
Related errors
- trash info has no Path
- invalid trash info path
- invalid original trash path
- invalid trash mount point
- Invalid cache stamp
AI-assisted analysis of sxyazi/yazi@94abcfa92f (2026-08-16).
Data as JSON: /api/errors/15ba7db65a8f8a73.
Report an issue: GitHub.