0x192/universal-android-debloater · error

Can't create cache directory

Error message

Can't create cache directory

What it means

setup_uad_dir takes an Option<PathBuf> base directory, calls unwrap() on it, appends "uad", and creates the directory tree with fs::create_dir_all(...).expect("Can't create cache directory"). The panic occurs when the base dir is None (unwrap panic) or when directory creation fails due to permissions, an invalid path, read-only filesystem, or I/O errors.

Source

Thrown at src/core/utils.rs:65

            PackageRow::new(p_name, state, description, uad_list, removal, false, false);
        user_package.push(package_row);
    }
    user_package.sort_by(|a, b| a.name.to_lowercase().cmp(&b.name.to_lowercase()));
    user_package
}

pub fn string_to_theme(theme: &str) -> Theme {
    match theme {
        "Dark" => Theme::Dark,
        "Light" => Theme::Light,
        "Lupin" => Theme::Lupin,
        _ => Theme::Lupin,
    }
}

pub fn setup_uad_dir(dir: Option<PathBuf>) -> PathBuf {
    let dir = dir.unwrap().join("uad");
    fs::create_dir_all(&dir).expect("Can't create cache directory");
    dir
}

pub fn open_url(dir: PathBuf) {
    #[cfg(target_os = "windows")]
    let output = Command::new("explorer").args([dir]).output();

    #[cfg(target_os = "macos")]
    let output = Command::new("open").args([dir]).output();

    #[cfg(not(any(target_os = "macos", target_os = "windows")))]
    let output = Command::new("xdg-open").args([dir]).output();

    match output {
        Ok(o) => {
            if !o.status.success() {
                let stderr = String::from_utf8(o.stderr).unwrap().trim_end().to_string();
                error!("Can't open the following URL: {}", stderr);

View on GitHub (pinned to 11f27c671c)

Solutions

  1. Always pass Some(valid_base_dir) pointing at a user-writable location (e.g. dirs::cache_dir()/data_dir())
  2. Check/fix permissions on the base directory, or pick another writable location
  3. Create parent directories first and handle create_dir_all's Result instead of expect()
  4. Return Result<PathBuf, io::Error> and show a setup error in the GUI rather than panicking

Example fix

// before
let dir = dir.unwrap().join("uad");
fs::create_dir_all(&dir).expect("Can't create cache directory");
// after
let dir = dir.unwrap_or_else(|| dirs::cache_dir().unwrap_or_else(|| ".".into())).join("uad");
fs::create_dir_all(&dir).unwrap_or_else(|e| {
    panic!("Can't create cache directory {}: {}", dir.display(), e)
})
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure a writable base dir exists before the app creates its cache dir
let base = dirs::cache_dir().expect("no usable base dir");
std::fs::create_dir_all(&base)?;
let probe = base.join(".probe");
std::fs::write(&probe, b"x")?;
std::fs::remove_file(&probe)?;

Type guard

fn base_dir_usable(dir: &Option<std::path::PathBuf>) -> bool {
    match dir {
        Some(p) => p.is_dir() && std::fs::metadata(p)
            .map(|m| !m.permissions().readonly()).unwrap_or(false),
        None => false,
    }
}

Try / catch

let result = std::panic::catch_unwind(|| setup_uad_dir(Some(base_dir.clone())));
match result {
    Ok(dir) => dir,
    Err(_) => { eprintln!("Can't create cache directory — pick a writable location"); std::env::temp_dir() }
}

Prevention

When it happens

Trigger: Called with None (dir.unwrap() panics) or with a base path the process cannot create (e.g. CONFIG_DIR/CACHE_DIR parent missing, permission denied, path too long or invalid characters).

Common situations: Flatpak/snap or Windows Program Files installs where the chosen data dir is not writable; HOME unset or redirected; the user selected an unwritable folder for cache; antivirus blocking directory creation.

Related errors


AI-assisted analysis of 0x192/universal-android-debloater@11f27c671c (2026-09-02). Data as JSON: /api/errors/6c669f29ffe47626. Report an issue: GitHub.