{"record":{"id":"6f8b213f00793898","repo":"sxyazi/yazi","slug":"unsupported-os-for-trash-operation","errorCode":null,"errorMessage":"Unsupported OS for trash operation","messagePattern":"Unsupported OS for trash operation","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"yazi-fs/src/engine/local/local.rs","lineNumber":222,"sourceCode":"\t\t{\n\t\t\ttokio::fs::symlink_file(original, self.path).await\n\t\t}\n\t}\n\n\t#[inline]\n\tasync fn symlink_metadata(&self) -> io::Result<Cha> {\n\t\tOk(Cha::new(\n\t\t\tself.path.file_name().unwrap_or_default(),\n\t\t\ttokio::fs::symlink_metadata(self.path).await?,\n\t\t))\n\t}\n\n\tasync fn trash(&self) -> io::Result<()> {\n\t\tlet path = self.path.to_owned();\n\t\ttokio::task::spawn_blocking(move || {\n\t\t\t#[cfg(target_os = \"android\")]\n\t\t\t{\n\t\t\t\tErr(io::Error::new(io::ErrorKind::Unsupported, \"Unsupported OS for trash operation\"))\n\t\t\t}\n\t\t\t#[cfg(target_os = \"macos\")]\n\t\t\t{\n\t\t\t\tuse trash::{TrashContext, macos::{DeleteMethod, TrashContextExtMacos}};\n\t\t\t\tlet mut ctx = TrashContext::default();\n\t\t\t\tctx.set_delete_method(DeleteMethod::NsFileManager);\n\t\t\t\tctx.delete(path).map_err(io::Error::other)\n\t\t\t}\n\t\t\t#[cfg(all(not(target_os = \"macos\"), not(target_os = \"android\")))]\n\t\t\t{\n\t\t\t\ttrash::delete(path).map_err(io::Error::other)\n\t\t\t}\n\t\t})\n\t\t.await?\n\t}\n\n\t#[inline]\n\tfn url(&self) -> Url<'_> { self.url }","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/sxyazi/yazi/blob/94abcfa92f4ad3f0a1aef6c1ea083cfb8aa6c8c2/yazi-fs/src/engine/local/local.rs#L204-L240","documentation":"`Local::trash()` (local.rs:222) moves a path to the OS trash via the `trash` crate. On `target_os = \"android\"` the operation is unconditionally rejected with `ErrorKind::Unsupported`, because Android has no freedesktop/macOS trash protocol the crate can use. macOS and other Unix/Windows targets take the `trash::delete` paths.","triggerScenarios":"Building yazi for Android (`aarch64-linux-android` target) and invoking any delete-to-trash action (default `d` keybinding or the trash plugin API) on any file.","commonSituations":"Running a Termux/build of yazi on Android; CI cross-compilation tests that execute trash code paths on an Android target.","solutions":["On Android, offer permanent delete instead of trash (bind the remove/delete-without-trash action).","Gate trash UI/actions with `#[cfg(not(target_os = \"android\"))]` or a runtime capability check so the action is not offered.","If trash semantics are required on Android, implement an app-private trash folder yourself and route deletes there."],"exampleFix":"// before\nlocal.trash().await?; // Err(Unsupported) on Android\n\n// after\n#[cfg(target_os = \"android\")]\nlocal.remove().await?; // permanent delete on Android\n#[cfg(not(target_os = \"android\"))]\nlocal.trash().await?;","handlingStrategy":"fallback","validationCode":"#[cfg(target_os = \"android\")]\nfn trash_supported() -> bool { false }\n#[cfg(not(target_os = \"android\"))]\nfn trash_supported() -> bool { true }","typeGuard":null,"tryCatchPattern":"match local.trash().await {\n    Ok(()) => {}\n    Err(e) if e.kind() == io::ErrorKind::Unsupported => {\n        // Android: fall back to permanent removal after user confirmation\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Detect the platform up front and hide trash actions on Android builds.","Bind delete-to-trash only on platforms where `trash_supported()` is true.","Offer an explicit 'delete permanently' binding as the Android default."],"tags":["android","trash","platform","unsupported-os"],"backgroundTag":null,"analyzedSha":"94abcfa92f4ad3f0a1aef6c1ea083cfb8aa6c8c2","analyzedAt":"2026-08-16T09:56:24.836Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}