{"record":{"id":"39d409cacdedafc0","repo":"sxyazi/yazi","slug":"invalidinput-39d409","errorCode":"InvalidInput","errorMessage":"invalid trash entry","messagePattern":"invalid trash entry","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"yazi-fs/src/trash/trash_id.rs","lineNumber":23,"sourceCode":"use yazi_shim::path::PathExt;\n\n#[derive(Clone, Debug)]\npub(crate) struct TrashId {\n\ttop: PathBuf,\n\trel: PathBuf,\n}\n\nimpl TrashId {\n\tpub(super) fn new<T, R>(top: T, rel: R) -> io::Result<Self>\n\twhere\n\t\tT: Into<PathBuf>,\n\t\tR: Into<PathBuf>,\n\t{\n\t\tlet top = top.into();\n\t\tlet rel = rel.into();\n\n\t\tif top.as_os_str().is_empty() || !rel.is_relative() {\n\t\t\treturn Err(io::Error::new(io::ErrorKind::InvalidInput, \"invalid trash entry\"));\n\t\t}\n\t\tif rel.has_parent_component() {\n\t\t\treturn Err(io::Error::new(io::ErrorKind::InvalidInput, \"invalid trash entry path\"));\n\t\t}\n\n\t\tOk(Self { top, rel })\n\t}\n\n\tpub(super) fn top(&self) -> &Path { &self.top }\n\n\tpub(super) fn rel(&self) -> &Path { &self.rel }\n\n\t#[cfg(target_os = \"macos\")]\n\tpub(super) fn path(&self) -> PathBuf {\n\t\tif self.has_rel() { self.top.join(&self.rel) } else { self.top.clone() }\n\t}\n\n\tpub(super) fn child(&self, name: &OsStr) -> io::Result<Self> {","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/sxyazi/yazi/blob/5f901b886b14de1f17460b6e52e9de5d67f8aba9/yazi-fs/src/trash/trash_id.rs#L5-L41","documentation":"Input validation in `TrashId::new`: the trash entry's top-level directory is empty or the entry's relative path is not relative, so the pair cannot form a valid (root, name) trash identifier. This is a constructor guard for internal trash bookkeeping; the faulting inputs are `top` and `rel`.","triggerScenarios":"Calling TrashId::new with an empty top path string, or with a rel argument that is absolute (starts with '/' or a root/prefix component).","commonSituations":"Building ids programmatically from user input or URLs where the rel segment accidentally includes an absolute path, or an empty top after stripping a prefix.","solutions":["Ensure top is a non-empty path to the item inside the trash","Pass rel as a bare relative path (e.g. 'sub/file.txt') without a leading separator","Validate inputs before constructing the id"],"exampleFix":"// before\nTrashId::new(\"\", Path::new(\"/abs/rel\"))?\n// after\nTrashId::new(\"/Users/me/.Trash/item\", Path::new(\"rel\"))?","handlingStrategy":"validation","validationCode":"fn valid_parts(top: &OsStr, rel: &Path) -> bool {\n    !top.is_empty() && rel.is_relative()\n}","typeGuard":"fn is_relative_bare(p: &Path) -> bool { p.is_relative() && !p.as_os_str().is_empty() }","tryCatchPattern":"match TrashId::new(top, rel) {\n    Err(e) if e.kind() == io::ErrorKind::InvalidInput => fix_paths_and_retry(),\n    other => other,\n}","preventionTips":["Strip root/prefix components from rel before constructing ids","Assert top is non-empty at the source of the path","Keep rel as a pure relative subpath"],"tags":["trash","io","invalid-input","path-validation"],"backgroundTag":"invalid-trash-id","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"}