{"record":{"id":"3b5af4e132fe37a9","repo":"sxyazi/yazi","slug":"trash-item-outside-of-trash-folders","errorCode":null,"errorMessage":"trash item outside of trash folders","messagePattern":"trash item outside of trash folders","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"yazi-fs/src/trash/freedesktop/trash.rs","lineNumber":39,"sourceCode":"\t\t\treturn Err(io::Error::new(io::ErrorKind::InvalidInput, \"trash item is not a directory\"));\n\t\t}\n\n\t\tfs::read_dir(&entry.backing)?\n\t\t\t.map(|dent| {\n\t\t\t\tlet dent = dent?;\n\t\t\t\tentry.child(dent.file_name())\n\t\t\t})\n\t\t\t.collect()\n\t}\n\n\tpub(crate) fn entry(&self, id: &TrashId) -> io::Result<TrashEntry> {\n\t\tlet info = TrashInfo::parse(id.top())?;\n\t\tif !os_limited::trash_folders()\n\t\t\t.map_err(io::Error::other)?\n\t\t\t.iter()\n\t\t\t.any(|folder| folder == &info.root)\n\t\t{\n\t\t\treturn Err(io::Error::new(io::ErrorKind::NotFound, \"trash item outside of trash folders\"));\n\t\t}\n\n\t\tif id.has_rel() && !fs::symlink_metadata(&info.backing)?.file_type().is_dir() {\n\t\t\treturn Err(io::Error::new(io::ErrorKind::InvalidInput, \"trash item is not a directory\"));\n\t\t}\n\n\t\tlet (backing, original) = if id.has_rel() {\n\t\t\t(info.backing.join(id.rel()), info.original.join(id.rel()))\n\t\t} else {\n\t\t\t(info.backing, info.original)\n\t\t};\n\t\tTrashEntry::new(id.clone(), backing, Some(original))\n\t}\n\n\tpub(crate) fn metadata(&self, entry: &TrashEntry, follow: bool) -> io::Result<Cha> {\n\t\tOk(if follow { entry.cha } else { entry.lcha })\n\t}\n","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/sxyazi/yazi/blob/a541adde4e5b082719a0f21a87eb3eab071ece58/yazi-fs/src/trash/freedesktop/trash.rs#L21-L57","documentation":"The freedesktop Trash::entry resolves a trash id by parsing its top-level .trashinfo and then verifying that the trash root recorded in the info belongs to a known trash folder (via os_limited::trash_folders()). If the info's root is not among the registered trash folders, it returns NotFound \"trash item outside of trash folders\". This prevents operating on trashinfo files found outside managed trash locations (e.g. arbitrary paths passed as ids).","triggerScenarios":"Building a trash id from a .trashinfo path located outside recognized trash folders (home Trash, top-level .Trash-<uid> dirs), then calling entry(); stale ids whose trash folder was moved, renamed, or mounted differently; a custom TRASH folder env/config change.","commonSituations":"External drives whose .Trash-1000 directory is no longer mounted; XDG_DATA_HOME changed since the id was created; ids persisted across sessions and the trash folder set changed.","solutions":["Ensure the drive/mount containing the .Trash-<uid> folder is mounted before accessing the trashed item.","Re-derive ids from the current trash listing (tops()/list()) instead of reusing persisted ids across mounts or config changes.","Check XDG_DATA_HOME / trash folder configuration so the folder that holds the item is registered as a trash folder.","Treat io::ErrorKind::NotFound as 'item no longer available' and refresh the trash view."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match trash.entry(&id).await {\n    Err(e) if e.kind() == std::io::ErrorKind::NotFound => refresh_trash_view(), // item's trash folder is gone/unmounted\n    other => other?,\n}","preventionTips":["Re-list trash contents instead of reusing ids persisted across sessions/mounts.","Ensure external drives' .Trash-<uid> folders are mounted before access.","Avoid changing XDG_DATA_HOME while trash ids are in use."],"tags":["trash","freedesktop","not-found","xdg"],"backgroundTag":"trash-item-outside-trash-folders","analyzedSha":"a541adde4e5b082719a0f21a87eb3eab071ece58","analyzedAt":"2026-09-02T18:38:25.566Z","contentChangedAt":"2026-09-02T18:38:25.566Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}