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

  1. Ensure the base directory (e.g. dirs::config_dir()) exists and is writable by the current user before launching.
  2. Set XDG_CONFIG_HOME / XDG_CACHE_HOME (or run with a valid HOME) to point to a writable location.
  3. Check disk space and that the target path is not an existing regular file.
  4. 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

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


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)