{"record":{"id":"c7a808516fe1a677","repo":"sxyazi/yazi","slug":"trash-info-has-no-path","errorCode":null,"errorMessage":"trash info has no Path","messagePattern":"trash info has no Path","errorType":"validation","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"yazi-fs/src/trash/freedesktop/trash_info.rs","lineNumber":55,"sourceCode":"\t\t}\n\n\t\tOk(Self { root: root.to_owned(), backing: root.join(\"files\").join(stem), original })\n\t}\n\n\tfn parse_original(info: &Path, root: &Path) -> io::Result<PathBuf> {\n\t\tlet mut reader = BufReader::new(File::open(info)?);\n\t\tlet mut line = Vec::new();\n\n\t\treader.read_until(b'\\n', &mut line)?;\n\t\tSelf::trim_line(&mut line);\n\t\tif line != b\"[Trash Info]\" {\n\t\t\treturn Err(io::Error::new(io::ErrorKind::InvalidData, \"invalid trash info header\"));\n\t\t}\n\n\t\tloop {\n\t\t\tline.clear();\n\t\t\tif reader.read_until(b'\\n', &mut line)? == 0 {\n\t\t\t\treturn Err(io::Error::new(io::ErrorKind::InvalidData, \"trash info has no Path\"));\n\t\t\t}\n\n\t\t\tSelf::trim_line(&mut line);\n\t\t\tlet Some(value) = line.strip_prefix(b\"Path=\") else { continue };\n\t\t\tlet decoded: Cow<[u8]> = percent_decode(value).into();\n\n\t\t\tlet path = Path::new(OsStr::from_bytes(decoded.as_ref()));\n\t\t\tif path.as_os_str().is_empty() || !path.is_absolute() && path.has_parent_component() {\n\t\t\t\treturn Err(io::Error::new(io::ErrorKind::InvalidData, \"invalid original trash path\"));\n\t\t\t}\n\n\t\t\treturn Ok(if path.is_absolute() {\n\t\t\t\tpath.to_owned()\n\t\t\t} else {\n\t\t\t\tSelf::mount_point(root)?.join(path)\n\t\t\t});\n\t\t}\n\t}","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/sxyazi/yazi/blob/94abcfa92f4ad3f0a1aef6c1ea083cfb8aa6c8c2/yazi-fs/src/trash/freedesktop/trash_info.rs#L37-L73","documentation":"`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.","triggerScenarios":"A `.trashinfo` containing only the `[Trash Info]` header, or with keys like `DeletionDate=` but no `Path=` line; files truncated mid-write.","commonSituations":"A crash or full disk while the trash implementation was writing metadata; trash info generated by buggy third-party tools.","solutions":["Add a valid `Path=<absolute-original-path>` line to the file and retry the restore.","If the original location is unknown, remove the `.trashinfo` and manually salvage the backing file from `<root>/files/`.","Report/fix whichever tool produced header-only trashinfo files."],"exampleFix":"# before\n[Trash Info]\nDeletionDate=2026-01-01T00:00:00\n\n# after\n[Trash Info]\nPath=/home/alice/report.pdf\nDeletionDate=2026-01-01T00:00:00","handlingStrategy":"try-catch","validationCode":"fn has_path_line(p: &std::path::Path) -> std::io::Result<bool> {\n    use std::io::BufRead;\n    let mut r = std::io::BufReader::new(std::fs::File::open(p)?);\n    let mut line = Vec::new();\n    r.read_until(b'\\n', &mut line)?; // header\n    loop {\n        line.clear();\n        if r.read_until(b'\\n', &mut line)? == 0 { return Ok(false); }\n        while matches!(line.last(), Some(b'\\n' | b'\\r')) { line.pop(); }\n        if line.starts_with(b\"Path=\") { return Ok(true); }\n    }\n}","typeGuard":null,"tryCatchPattern":"match trash.entry(&id) {\n    Ok(e) => { /* ... */ }\n    Err(e) if e.kind() == io::ErrorKind::InvalidData => {\n        // missing Path= line: add `Path=/abs/original` to the .trashinfo, or purge the item\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Never truncate or hand-strip lines from .trashinfo files; Path= is mandatory.","After crashes, scan trash info for header-only files and repair them.","When generating metadata, write Path= first so partial writes still often succeed."],"tags":["trash","trashinfo","missing-path","corruption","invalid-data"],"backgroundTag":null,"analyzedSha":"94abcfa92f4ad3f0a1aef6c1ea083cfb8aa6c8c2","analyzedAt":"2026-08-16T09:56:24.836Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}