sxyazi/yazi · error · io::Error

trash item has no put-back location

Error message

trash item has no put-back location

What it means

Returned by Trash::restore on macOS when an entry's original (put-back) path is None, i.e. ~/.Trash/.DS_Store has no usable ptbL/ptbN record for it (errors 60-62 were swallowed earlier and left original empty). This is the user-visible form of 'cannot put back': yazi refuses to guess a destination and fails the whole restore batch with io::ErrorKind::NotFound.

Source

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

		let changed = !latest.cha.hits(current.cha)
			|| latest.extra.link_to() != current.extra.link_to()
			|| latest.extra.backing() != current.extra.backing();

		Ok(changed.then_some(latest))
	}

	pub(crate) fn remove_file(&self, entry: &TrashEntry) -> io::Result<()> {
		fs::remove_file(&entry.backing)
	}

	pub(crate) fn remove_dir(&self, entry: &TrashEntry) -> io::Result<()> {
		fs::remove_dir(&entry.backing)
	}

	pub(crate) fn restore(&self, entries: TrashEntries) -> io::Result<()> {
		for entry in entries {
			let to = entry.original.as_ref().ok_or_else(|| {
				io::Error::new(io::ErrorKind::NotFound, "trash item has no put-back location")
			})?;

			restore_item(&entry.backing, &to)?;
		}
		Ok(())
	}

	pub(crate) fn rename(&self, entry: &TrashEntry, path: &Path) -> io::Result<()> {
		fs::rename(&entry.backing, path)
	}

	pub(crate) fn empty(&self) -> io::Result<()> {
		let root = self.root()?;
		for dent in ok_or_not_found!(fs::read_dir(root), return Ok(())) {
			let dent = dent?;
			if dent.file_type()?.is_dir() {
				fs::remove_dir_all(dent.path())?;
			} else {

View on GitHub (pinned to 94abcfa92f)

Solutions

  1. Filter the selection: restore only entries with original ~= nil, and for the rest move them manually out of ~/.Trash or use Trash:rename to pick a destination.
  2. If Finder put-back is important, move the item back and re-trash it from Finder, then restore.
  3. Handle the (false, err) return of Trash:restore in Lua and report which items need manual handling instead of failing silently.

Example fix

-- Lua: before
local ok, err = ya.fs("trash"):restore(entries)
-- after: split restorable vs manual, keep the batch atomic from the user's view
local trash = ya.fs("trash")
local restorable, manual = {}, {}
for _, e in ipairs(entries) do
  (e.original and table.insert(restorable, e) or table.insert(manual, e))
end
if #restorable > 0 then local ok, err = trash:restore(restorable); end
-- prompt the user for a destination for each entry in `manual`
Defensive patterns

Strategy: validation

Validate before calling

-- Lua: partition before restoring
local restorable, manual = {}, {}
for _, e in ipairs(entries) do
  if e.original ~= nil then table.insert(restorable, e) else table.insert(manual, e) end
end
if #restorable > 0 then ya.fs("trash"):restore(restorable) end

Type guard

local function is_restorable(e) return e.original ~= nil end

Try / catch

local ok, err = ya.fs("trash"):restore(entries)
if not ok then
  ya.notify({ title = "Restore failed", content = tostring(err), level = "warn", timeout = 5 })
  -- partial batch: re-list the trash to see what moved and what stayed
end

Prevention

When it happens

Trigger: Restoring items that were moved into ~/.Trash by `mv`, shell scripts, or third-party tools that never write .DS_Store; restoring after .DS_Store was deleted/reset; restoring items whose ptbN failed the put-back-name validation.

Common situations: Power users trashing from the terminal and later trying 'put back' in yazi; cleanup utilities wiping .DS_Store; mixed selections where only some items lack put-back info — the first missing item aborts the loop, leaving earlier items already restored.

Related errors


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