sxyazi/yazi · error · io::Error

invalid trash entry

Error message

invalid trash entry

What it means

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.

Source

Thrown at yazi-fs/src/trash/trash_id.rs:23

use yazi_shim::path::PathExt;

#[derive(Clone, Debug)]
pub(crate) struct TrashId {
	top: PathBuf,
	rel: PathBuf,
}

impl TrashId {
	pub(super) fn new<T, R>(top: T, rel: R) -> io::Result<Self>
	where
		T: Into<PathBuf>,
		R: Into<PathBuf>,
	{
		let top = top.into();
		let rel = rel.into();

		if top.as_os_str().is_empty() || !rel.is_relative() {
			return Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid trash entry"));
		}
		if rel.has_parent_component() {
			return Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid trash entry path"));
		}

		Ok(Self { top, rel })
	}

	pub(super) fn top(&self) -> &Path { &self.top }

	pub(super) fn rel(&self) -> &Path { &self.rel }

	#[cfg(target_os = "macos")]
	pub(super) fn path(&self) -> PathBuf {
		if self.has_rel() { self.top.join(&self.rel) } else { self.top.clone() }
	}

	pub(super) fn child(&self, name: &OsStr) -> io::Result<Self> {

View on GitHub (pinned to 94abcfa92f)

Solutions

  1. Always non-empty absolute top; keep rel relative ('' for top-level items, 'sub/file' inside).
  2. Prefer ids taken from Trash:list/Trash:entry instead of hand-building them.
  3. Validate the table shape before passing it to entry().

Example fix

-- Lua: before
local e = ya.fs("trash"):entry({ top = "", rel = "/a.txt" })
-- after
local e = ya.fs("trash"):entry({ top = "/Users/me/.Trash/a.txt", rel = "" })
Defensive patterns

Strategy: validation

Validate before calling

-- Lua: validate the id table before calling entry()
local function valid_id(t)
  return type(t) == "table"
    and type(t.top) == "string" and #t.top > 0
    and type(t.rel) == "string" and t.rel:sub(1, 1) ~= "/"
end
if valid_id(id) then local e = ya.fs("trash"):entry(id) end

Type guard

local function is_trash_id_like(t)
  return type(t) == "table" and type(t.top) == "string" and type(t.rel) == "string"
end

Try / catch

local e, err = ya.fs("trash"):entry(id)
if e == nil and err.kind == "invalid-input" then
  -- bad id shape: rebuild it from a listed entry
end

Prevention

When it happens

Trigger: Trash:entry({ top = '', rel = '' }) — empty top; rel = '/foo' or 'C:\foo' — absolute rel; a table missing top/rel keys yielding empty values.

Common situations: Plugins deriving ids from Url strings or splitting paths incorrectly; passing trash:// URLs un-parsed; empty-string defaults when table.get returns nothing.

Related errors


AI-assisted analysis of sxyazi/yazi@94abcfa92f (2026-08-16). Data as JSON: /api/errors/2a8384ee9a554fc8. Report an issue: GitHub.