Universal-Debloater-Alliance/universal-android-debloater-next-generation · error

Unable to write file

Error message

Unable to write file

What it means

After successfully downloading the remote debloat list text, load_debloat_lists persists it to the cached lists file with `fs::write(...).expect("Unable to write file")`. If the filesystem write fails for any reason, this panics, aborting the whole load operation even though the download itself succeeded.

Solutions

  1. Replace .expect with error propagation: log a warning and continue using the in-memory `text`/`list` even if caching failed.
  2. Ensure the cache directory exists with correct permissions before writing (setup_uad_dir / create_dir_all) and check writability.
  3. Fall back to the previous cached file if the write fails, keeping the app functional.
  4. Free disk space or fix permissions on the UAD cache directory.

Example fix

// before
fs::write(cached_uad_lists.clone(), &text).expect("Unable to write file");
// after
if let Err(e) = fs::write(&cached_uad_lists, &text) {
    warn!("Could not cache debloat list: {e}");
}
Defensive patterns

Strategy: try-catch

Validate before calling

if !cached_uad_lists.parent().map_or(false, |p| p.exists()) {
    std::fs::create_dir_all(cached_uad_lists.parent().unwrap())?;
}
let writable = std::fs::OpenOptions::new().append(true).open(&cached_uad_lists).is_ok();
if !writable { eprintln!("cache file not writable: {:?}", cached_uad_lists); }

Try / catch

if let Err(e) = fs::write(&cached_uad_lists, &text) {
    warn!("caching failed, continuing with in-memory list: {e}");
}

Prevention

When it happens

Trigger: Calling load_debloat_lists (via update_lists, list_packages, init_apps_view, etc.) when the cache directory is missing, read-only, or full, or the cached UAD lists file is locked by another process / lacks write permission.

Common situations: Read-only config/home directories (flatpak/sandboxed installs, restricted CI users); disk full; CACHE_DIR pointing at a non-writable path after a migration; antivirus or backup tooling holding the file open on Windows.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of Universal-Debloater-Alliance/universal-android-debloater-next-generation@64465c850c (2026-09-12). Data as JSON: /api/errors/fc3818c0cf7c30e0. Report an issue: GitHub.

Appendix: source

Thrown at crates/uad-core/src/uad_lists.rs:231

                "https://raw.githubusercontent.com\
                    /Universal-Debloater-Alliance\
                    /universal-android-debloater\
                    /main\
                    /resources\
                    /assets\
                    /{LIST_FNAME}"
            ))
            .call()
            {
                Ok(mut data) => {
                    // https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/discussions/608
                    let text = data
                        .body_mut()
                        .with_config()
                        .limit(1 << (3 + 10 + 10))
                        .read_to_string()
                        .expect("remote list is bigger than 8MiB");
                    fs::write(cached_uad_lists.clone(), &text).expect("Unable to write file");
                    let list: PackageHashMap =
                        serde_json::from_str(&text).expect("Unable to parse");
                    OperationResult::Ok(list)
                }
                Err(e) => {
                    warn!("Could not load remote debloat list: {e}");
                    error = true;
                    OperationResult::Retry(PackageHashMap::new())
                }
            }
        })
        .unwrap_or_else(|_| get_local_lists())
    } else {
        warn!("Could not load remote debloat list");
        get_local_lists()
    };

    (if error { Err } else { Ok })(list)

View on GitHub (pinned to 64465c850c)