sxyazi/yazi · warning · io::Error

invalid trash put-back name

Error message

invalid trash put-back name

What it means

Thrown by DsStore::join on macOS when the ptbN put-back name parsed from ~/.Trash/.DS_Store is not a single normal path component (e.g. '/', '..', 'a/b'). This is a validation step that prevents path traversal or malformed joins before constructing the original path. The error is swallowed with .ok() upstream, leaving the entry without put-back info.

Source

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

		Ok(locations)
	}

	pub(super) fn join(&self, rel: &Path) -> io::Result<PathBuf> {
		if !rel.is_relative() || rel.has_parent_component() {
			return Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid trash entry path"));
		}

		let parent = self.parent.as_deref().ok_or_else(|| {
			io::Error::new(io::ErrorKind::InvalidData, "trash item has no put-back location")
		})?;

		let name = self.name.as_deref().ok_or_else(|| {
			io::Error::new(io::ErrorKind::InvalidData, "trash item has no put-back name")
		})?;

		let mut components = Path::new(name).components();
		if !matches!(components.next(), Some(Component::Normal(_))) || components.next().is_some() {
			return Err(io::Error::new(io::ErrorKind::InvalidData, "invalid trash put-back name"));
		}

		let top_path = Path::new("/").join(parent).join(name);
		Ok(if rel.as_os_str().is_empty() { top_path } else { top_path.join(rel) })
	}
}

View on GitHub (pinned to 94abcfa92f)

Solutions

  1. Treat the item as manually restorable: move it out of ~/.Trash yourself or use Trash:rename with an explicit destination.
  2. Delete or rebuild ~/.Trash/.DS_Store (Finder recreates it) so future records parse cleanly.
  3. If you parse .DS_Store yourself, validate put-back names the same way (exactly one Component::Normal) before joining.
Defensive patterns

Strategy: validation

Validate before calling

-- The library already validates ptbN; you only see original == nil.
local safe = {}
for _, e in ipairs(entries) do
  if e.original ~= nil then table.insert(safe, e) end
end

Type guard

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

Try / catch

if not trash:restore(safe) then -- fall back to manual move via Trash:rename with an explicit destination end

Prevention

When it happens

Trigger: The ptbN Ustr value fails the components() check: first component is RootDir/ParentDir/CurDir, or there is more than one component (name contains a separator).

Common situations: Corrupted or hand-edited .DS_Store; maliciously crafted .DS_Store aiming at path traversal; metadata written by non-Finder tools with unsanitized names.

Related errors


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