{"record":{"id":"2a8384ee9a554fc8","repo":"sxyazi/yazi","slug":"invalid-trash-entry","errorCode":null,"errorMessage":"invalid trash entry","messagePattern":"invalid trash entry","errorType":"validation","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/94abcfa92f4ad3f0a1aef6c1ea083cfb8aa6c8c2/yazi-fs/src/trash/trash_id.rs#L5-L41","documentation":"Returned by TrashId::new when top is empty or rel is not a relative path. TrashId is the (top, rel) address of a trash item; top must be a non-empty path and rel must be relative (no leading '/'). Constructed from Lua tables { top = ..., rel = ... } in FromLua, so malformed tables surface as io::ErrorKind::InvalidInput.","triggerScenarios":"Trash:entry({ top = '', rel = '' }) — empty top; rel = '/foo' or 'C:\\foo' — absolute rel; a table missing top/rel keys yielding empty values.","commonSituations":"Plugins deriving ids from Url strings or splitting paths incorrectly; passing trash:// URLs un-parsed; empty-string defaults when table.get returns nothing.","solutions":["Always non-empty absolute top; keep rel relative ('' for top-level items, 'sub/file' inside).","Prefer ids taken from Trash:list/Trash:entry instead of hand-building them.","Validate the table shape before passing it to entry()."],"exampleFix":"-- Lua: before\nlocal e = ya.fs(\"trash\"):entry({ top = \"\", rel = \"/a.txt\" })\n-- after\nlocal e = ya.fs(\"trash\"):entry({ top = \"/Users/me/.Trash/a.txt\", rel = \"\" })","handlingStrategy":"validation","validationCode":"-- Lua: validate the id table before calling entry()\nlocal function valid_id(t)\n  return type(t) == \"table\"\n    and type(t.top) == \"string\" and #t.top > 0\n    and type(t.rel) == \"string\" and t.rel:sub(1, 1) ~= \"/\"\nend\nif valid_id(id) then local e = ya.fs(\"trash\"):entry(id) end","typeGuard":"local function is_trash_id_like(t)\n  return type(t) == \"table\" and type(t.top) == \"string\" and type(t.rel) == \"string\"\nend","tryCatchPattern":"local e, err = ya.fs(\"trash\"):entry(id)\nif e == nil and err.kind == \"invalid-input\" then\n  -- bad id shape: rebuild it from a listed entry\nend","preventionTips":["top: non-empty absolute path; rel: relative path or ''.","Reuse ids from list()/entry() instead of constructing tables from strings.","Unit-test id construction with edge cases: '', '/', 'a/../b'."],"tags":["trash","trash-id","invalid-input","validation"],"backgroundTag":null,"analyzedSha":"94abcfa92f4ad3f0a1aef6c1ea083cfb8aa6c8c2","analyzedAt":"2026-08-16T09:56:24.836Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}