Universal-Debloater-Alliance/universal-android-debloater-next-generation · critical
{e}
Error message
{e} What it means
setup_uad_dir creates the app's "uad" subdirectory under a given base path and panics if fs::create_dir_all fails. The panic message is the raw std::io::Error Display, so the text is whatever the OS reported (e.g. permission denied). It is thrown because the library treats an unusable data directory as unrecoverable at startup.
Solutions
- Ensure the base directory (e.g. dirs::config_dir()) exists and is writable by the current user before launching.
- Set XDG_CONFIG_HOME / XDG_CACHE_HOME (or run with a valid HOME) to point to a writable location.
- Check disk space and that the target path is not an existing regular file.
- Catch the panic upstream (catch_unwind) or call setup_uad_dir early on a known-good path to fail fast with a clear message.
Example fix
// before
let dir = base.join("uad"); // panics if unwritable
// after
let dir = base.join("uad");
if let Err(e) = std::fs::create_dir_all(&dir) {
eprintln!("cannot create {}: {e}", dir.display());
std::process::exit(1);
} Defensive patterns
Strategy: validation
Validate before calling
let dir = base.join("uad");
if !base.is_dir() { return Err("base path is not a directory"); }
let probe = dir.join(".write_test");
std::fs::write(&probe, b"").map_err(|e| format!("dir not writable: {e}"))?;
let _ = std::fs::remove_file(&probe); Type guard
fn is_writable_dir(p: &std::path::Path) -> bool {
p.is_dir() && std::fs::OpenOptions::new().write(true).open(p).is_ok()
} Try / catch
let dir = std::panic::catch_unwind(|| setup_uad_dir(&base))
.unwrap_or_else(|_| { eprintln!("cannot create uad dir under {}", base.display()); std::process::exit(1); }); Prevention
- Verify HOME/XDG_CONFIG_HOME are set and writable before launching the app.
- Never point the base path at an existing regular file.
- Run an early write-probe at startup to fail fast with a clear message.
- In sandboxes (flatpak/snap), declare filesystem permissions for the config path.
When it happens
Trigger: Calling setup_uad_dir (directly or via CONFIG_DIR/CACHE_DIR LazyLocks in lib.rs) when the base path's parent does not exist and cannot be created, or exists but is not writable.
Common situations: Read-only $HOME or $XDG_CONFIG_HOME, running as a service user without a home directory, sandboxed/flatpak environments blocking writes, disk full, or base path resolving to a file instead of a directory.
Understand the failure class
Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.
Related errors
- Could not write config file to disk!
- There must be 1 tab after serial
- Can't detect config dir
- Can't detect cache dir
- Unable to write file
AI-assisted analysis of Universal-Debloater-Alliance/universal-android-debloater-next-generation@64465c850c (2026-09-12).
Data as JSON: /api/errors/db6960df7fe75b14.
Report an issue: GitHub.
Appendix: source
Thrown at crates/uad-core/src/utils.rs:139
let package = CorePackage {
name: p_name.clone(),
description,
removal,
state,
list,
};
user_package.push(package);
}
user_package.sort_by_key(|package| package.name.to_lowercase());
user_package
}
#[must_use]
pub fn setup_uad_dir(dir: &Path) -> PathBuf {
let dir = dir.join("uad");
if let Err(e) = fs::create_dir_all(&dir) {
error!("Can't create directory: {}", dir.display());
panic!("{e}");
}
dir
}
/// Open a directory or file with the system's default file manager.
pub fn open_url(dir: PathBuf) {
const OPENER: &str = match std::env::consts::OS.as_bytes() {
b"windows" => "explorer",
b"macos" => "open",
// "linux"
_ => "xdg-open",
};
match std::process::Command::new(OPENER).arg(dir).output() {
Ok(o) => {
if !o.status.success() {
// Use lossy conversion for stderr - some systems (like Windows)
// may output non-UTF8 characters in error messages
let stderr = String::from_utf8_lossy(&o.stderr);View on GitHub (pinned to 64465c850c)