sxyazi/yazi · error · io::Error

trash item is not a directory

Error message

trash item is not a directory

What it means

Returned by Trash::list on macOS when it is called with Some(entry) whose lcha (link metadata) says the item is not a directory. Trash listing is hierarchical: only directories can be expanded, so asking for the children of a trashed file is an invalid-input error (io::ErrorKind::InvalidInput).

Source

Thrown at yazi-fs/src/trash/macos/trash.rs:15

use std::{fs, io, path::{Path, PathBuf}};

use yazi_macro::ok_or_not_found;

use super::{super::{TrashCha, TrashEntries, TrashEntry, TrashId, restore_item}, DsStore};
use crate::{cha::Cha, file::File};

pub struct Trash;

impl Trash {
	pub(crate) fn new() -> io::Result<Self> { Ok(Self) }

	pub(crate) fn list(&self, entry: Option<&TrashEntry>) -> io::Result<Vec<TrashEntry>> {
		if entry.is_some_and(|entry| !entry.lcha.is_dir()) {
			return Err(io::Error::new(io::ErrorKind::InvalidInput, "trash item is not a directory"));
		}

		let root = self.root()?;
		let store = if entry.is_none() {
			DsStore::parse(&root.join(".DS_Store")).unwrap_or_default()
		} else {
			Default::default()
		};

		let path = entry.map_or(&root, |entry| &entry.backing);
		let it = match fs::read_dir(path) {
			Ok(it) => it,
			Err(e) if e.kind() == io::ErrorKind::NotFound && entry.is_none() => return Ok(vec![]),
			Err(e) => return Err(e),
		};

		it.map(|dent| {
			let dent = dent?;

View on GitHub (pinned to 94abcfa92f)

Solutions

  1. Only call list with nil (trash root) or with an entry whose lcha.is_dir() is true.
  2. In UI flows, gate 'enter directory' on the entry kind, not on the current tab mode.
  3. Re-fetch the entry (Trash:entry) if the cached lcha may be stale, then re-check is_dir().

Example fix

-- Lua: before
local items = ya.fs("trash"):list(entry)
-- after
local trash = ya.fs("trash")
local items = entry and entry.lcha.is_dir and trash:list(entry) or trash:list()
Defensive patterns

Strategy: type-guard

Validate before calling

-- Lua: only expand real directories (lcha = non-followed metadata)
if entry == nil or entry.lcha.is_dir then
  local items = ya.fs("trash"):list(entry)
end

Type guard

local function is_trash_dir(e)
  return e ~= nil and e.lcha ~= nil and e.lcha.is_dir == true
end

Try / catch

local items, err = ya.fs("trash"):list(entry)
if items == nil and err.kind == "invalid-input" then
  -- hovered item is a file: open/peek it instead of expanding
end

Prevention

When it happens

Trigger: Trash:list(entry) / the Lua Trash:list with a file entry, e.g. pressing enter or expanding a regular file (or a symlink to a file, since lcha is the non-followed metadata) inside the trash view.

Common situations: Plugin or keymap that unconditionally calls list on the hovered trash item; hover state raced (entry became a file after a revalidate); trying to 'open' a file in trash as if it were a folder.

Related errors


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