sxyazi/yazi · error · io::Error
trash item has no put-back location
Error message
trash item has no put-back location
What it means
Thrown by the Windows trash backend when expanding (listing children of) a trashed directory whose TrashEntry carries no `original` put-back path. Child entries are built as `original.join(name)`, so without a recorded original location the expansion cannot proceed. The Recycle Bin normally records the original location, but items from some network/removable drives or entries reconstructed from a stale TrashId may lack it.
Source
Thrown at yazi-fs/src/trash/windows/trash.rs:32
impl Trash {
pub(crate) fn new() -> io::Result<Self> {
COM.with(|result| {
result.as_ref().map(|_| Self).map_err(|e| io::Error::new(e.kind(), e.to_string()))
})
}
pub(crate) fn list(&self, entry: Option<&TrashEntry>) -> io::Result<Vec<TrashEntry>> {
let Some(entry) = entry else {
return self.tops();
};
if !entry.lcha.is_dir() || entry.lcha.is_indirect() {
return Err(io::Error::new(io::ErrorKind::InvalidInput, "trash item is not a directory"));
}
let original = entry.original.as_deref().ok_or_else(|| {
io::Error::new(io::ErrorKind::NotFound, "trash item has no put-back location")
})?;
self
.resolve(entry)?
.children()?
.into_iter()
.map(|item| {
let name = item.display_name(SIGDN_PARENTRELATIVEPARSING)?;
item.entry(entry.id.child(&name)?, Some(original.join(&name)))
})
.collect()
}
pub(crate) fn entry(&self, id: &TrashId) -> io::Result<TrashEntry> {
let top = ShellItem::top(id.top())?;
let original = top.original()?;
if !id.has_rel() {
return top.entry(id.clone(), Some(original));View on GitHub (pinned to 94abcfa92f)
Solutions
- Check `entry.original.is_some()` before calling `list(Some(&entry))` and treat the entry as an opaque leaf when it is None
- If the entry should be expandable, re-list the bin from the top (`list(None)`) to rebuild entries with fresh original locations
- If put-back info is genuinely unrecorded by the shell, only permanent removal is possible — do not retry listing
Example fix
// before
let children = trash.list(Some(&entry))?;
// after
if entry.original.is_none() {
// Shell recorded no put-back location; cannot expand children
return Ok(vec![]);
}
let children = trash.list(Some(&entry))?; Defensive patterns
Strategy: validation
Validate before calling
// Rust
let expandable = entry.lcha.is_dir() && !entry.lcha.is_indirect() && entry.original.is_some();
if expandable {
let children = trash.list(Some(&entry))?;
} Type guard
fn can_expand_trash(e: &TrashEntry) -> bool {
e.lcha.is_dir() && !e.lcha.is_indirect() && e.original.is_some()
} Try / catch
match trash.list(Some(&entry)) {
Err(e) if e.kind() == io::ErrorKind::NotFound && e.to_string().contains("put-back") => Ok(vec![]),
other => other,
} Prevention
- Check entry.original before expanding trash directories
- Re-list the bin from the top when trash state may be stale
- Do not construct TrashEntry values without original in tests/fixtures
When it happens
Trigger: Calling `Trash::list(Some(&entry))` on Windows where `entry.lcha` is a directory and not a symlink, but `entry.original` is None — e.g. a trashed directory deleted from a network share, or an entry revived from a cached TrashId without put-back info.
Common situations: Browsing the trash of a machine with items deleted from UNC paths or removable media; restoring a yazi session whose trash state went stale after the Recycle Bin changed; automated tests that construct TrashEntry values without `original`.
Related errors
- trash directory is not empty
- restore target already exists: {to:?}
- trash item is not a directory
- Destination already exists
- bundled rust-lld setup requires a Unix host
AI-assisted analysis of sxyazi/yazi@94abcfa92f (2026-08-16).
Data as JSON: /api/errors/f3dcceed7306a0de.
Report an issue: GitHub.