sxyazi/yazi · error · io::Error

InvalidInput

InvalidInput

Error message

trash item is not a directory

What it means

Trash::list on macOS enumerates the children of a trashed directory; it requires the given entry to actually be a directory (checked via the entry's lcha cached cha). Calling list with a trashed file entry is an invalid input.

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 8ebf930f17)

Solutions

  1. Check entry.lcha.is_dir() before calling list
  2. Call list with None to list the trash root instead
  3. Handle the error and treat the file entry as childless

Example fix

// before
let children = trash.list(Some(&entry))?;
// after
let children = if entry.lcha.is_dir() { trash.list(Some(&entry))? } else { Vec::new() };
Defensive patterns

Strategy: validation

Validate before calling

if entry.lcha.is_dir() { trash.list(Some(entry))?; }

Type guard

fn is_trashed_dir(entry: &TrashEntry) -> bool { entry.lcha.is_dir() }

Try / catch

match trash.list(Some(entry)) {
    Err(e) if e.kind() == io::ErrorKind::InvalidInput => Vec::new(), // non-directory: no children
    other => other?,
}

Prevention

When it happens

Trigger: Calling Trash::list(Some(entry)) where entry.lcha.is_dir() is false — i.e. listing contents of a trashed regular file, symlink, or other non-directory.

Common situations: Caller listed the trash, picked an entry without checking its kind, and tried to recurse into it; UI code hovering a trashed file and requesting its children.

Related errors


AI-assisted analysis of sxyazi/yazi@8ebf930f17 (2026-09-02). Data as JSON: /api/errors/3c6483169d6bd4cd. Report an issue: GitHub.