{"record":{"id":"839c93c685257457","repo":"sxyazi/yazi","slug":"invalidinput-839c93","errorCode":"InvalidInput","errorMessage":"trash item is not a directory","messagePattern":"trash item is not a directory","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"yazi-fs/src/trash/windows/trash.rs","lineNumber":28,"sourceCode":"\tstatic COM: io::Result<Com> = Com::new();\n}\n\npub struct Trash;\n\nimpl Trash {\n\tpub(crate) fn new() -> io::Result<Self> {\n\t\tCOM.with(|result| {\n\t\t\tresult.as_ref().map(|_| Self).map_err(|e| io::Error::new(e.kind(), e.to_string()))\n\t\t})\n\t}\n\n\tpub(crate) fn list(&self, entry: Option<&TrashEntry>) -> io::Result<Vec<TrashEntry>> {\n\t\tlet Some(entry) = entry else {\n\t\t\treturn self.tops();\n\t\t};\n\n\t\tif !entry.lcha.is_dir() || entry.lcha.is_indirect() {\n\t\t\treturn Err(io::Error::new(io::ErrorKind::InvalidInput, \"trash item is not a directory\"));\n\t\t}\n\n\t\tlet original = entry.original.as_deref().ok_or_else(|| {\n\t\t\tio::Error::new(io::ErrorKind::NotFound, \"trash item has no put-back location\")\n\t\t})?;\n\n\t\tself\n\t\t\t.resolve(entry)?\n\t\t\t.children()?\n\t\t\t.into_iter()\n\t\t\t.map(|item| {\n\t\t\t\tlet name = item.display_name(SIGDN_PARENTRELATIVEPARSING)?;\n\t\t\t\titem.entry(entry.id.child(&name)?, Some(original.join(&name)))\n\t\t\t})\n\t\t\t.collect()\n\t}\n\n\tpub(crate) fn entry(&self, id: &TrashId) -> io::Result<TrashEntry> {","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/sxyazi/yazi/blob/5f901b886b14de1f17460b6e52e9de5d67f8aba9/yazi-fs/src/trash/windows/trash.rs#L10-L46","documentation":"In the Windows trash backend, `list()` with a parent `TrashEntry` enumerates its children in the recycle-bin folder. This error is returned when the parent entry's cached attributes (`lcha`) indicate it is not a directory, or is an indirect/link item, so it cannot have children to enumerate. It is a caller-contract violation: `list(Some(entry))` must be given a directory trash item.","triggerScenarios":"Calling `Trash::list(Some(entry))` where `entry.lcha` is not a dir or `is_indirect()` is true — e.g. passing a trashed file instead of a trashed folder, or a shortcut/indirect item.","commonSituations":"Building a tree view of the recycle bin and feeding non-directory entries into the child-listing call; stale attribute caches after the entry changed.","solutions":["Check `entry.lcha.is_dir() && !entry.lcha.is_indirect()` before calling list with a parent entry.","Only pass directory entries to the child enumeration path; list files as leaves.","Re-fetch the entry's metadata if the cached lcha may be stale.","Treat the error as InvalidInput and skip non-directory entries during traversal."],"exampleFix":"// before\nlet children = trash.list(Some(&entry))?;\n// after\nif entry.lcha.is_dir() && !entry.lcha.is_indirect() {\n    let children = trash.list(Some(&entry))?;\n} else {\n    // leaf entry: no children\n}","handlingStrategy":"validation","validationCode":"if !(entry.lcha.is_dir() && !entry.lcha.is_indirect()) {\n    return Ok(()); // leaf: no children to list\n}\nlet children = trash.list(Some(&entry))?;","typeGuard":"fn is_listable_dir(entry: &TrashEntry) -> bool {\n    entry.lcha.is_dir() && !entry.lcha.is_indirect()\n}","tryCatchPattern":"match trash.list(Some(&entry)) {\n    Ok(children) => children,\n    Err(e) if e.kind() == std::io::ErrorKind::InvalidInput => Vec::new(),\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Check is_dir/is_indirect before child enumeration.","Treat non-directory trash items as leaves.","Refresh cached attributes if entries may be stale."],"tags":["windows","trash","invalid-argument","filesystem","rust"],"backgroundTag":"not-a-directory","analyzedSha":"5f901b886b14de1f17460b6e52e9de5d67f8aba9","analyzedAt":"2026-09-02T18:38:25.566Z","contentChangedAt":"2026-09-02T18:38:25.566Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}