0x192/universal-android-debloater · error
Unable to write file
Error message
Unable to write file
What it means
After downloading the debloat list, the code writes the text to the cached file (CACHE_DIR/uad_lists.json) with fs::write(...).expect("Unable to write file"). A filesystem failure (missing cache directory, permissions, full disk) panics the application even though the download itself succeeded.
Source
Thrown at src/core/uad_lists.rs:189
)
}
}
type PackageHashMap = HashMap<String, Package>;
pub fn load_debloat_lists(remote: bool) -> (Result<PackageHashMap, PackageHashMap>, bool) {
let cached_uad_lists: PathBuf = CACHE_DIR.join("uad_lists.json");
let mut error = false;
let list: Vec<Package> = if remote {
retry(Fixed::from_millis(1000).take(60), || {
match ureq::get(
"https://raw.githubusercontent.com/0x192/universal-android-debloater/\
main/resources/assets/uad_lists.json",
)
.call()
{
Ok(data) => {
let text = data.into_string().expect("response should be Ok type");
fs::write(cached_uad_lists.clone(), &text).expect("Unable to write file");
let list = 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(Vec::<Package>::new())
}
}
})
.map_or_else(|_| get_local_lists(), |list| list)
} else {
warn!("Could not load remote debloat list");
get_local_lists()
};
// TODO: Do it without intermediary Vec?
let mut package_lists = HashMap::new();View on GitHub (pinned to 11f27c671c)
Solutions
- Ensure the cache directory exists (create_dir_all on CACHE_DIR) before writing
- Check permissions and free disk space on the cache location
- Match on fs::write result and fall back to the bundled/embedded list instead of panicking
- Log and degrade gracefully: keep the in-memory list (it parses fine) even if caching fails
Example fix
// before
fs::write(cached_uad_lists.clone(), &text).expect("Unable to write file");
// after
let _ = fs::create_dir_all(cached_uad_lists.parent().unwrap());
if let Err(e) = fs::write(cached_uad_lists.clone(), &text) {
warn!("Unable to write cache file: {}", e);
} Defensive patterns
Strategy: validation
Validate before calling
let cache = dirs::cache_dir().unwrap().join("uad");
std::fs::create_dir_all(&cache)?;
let test = cache.join(".write_test");
std::fs::write(&test, b"ok")?;
std::fs::remove_file(&test)?; // cache dir is writable Type guard
fn cache_writable(dir: &std::path::Path) -> bool {
dir.exists() && std::fs::metadata(dir)
.map(|m| !m.permissions().readonly())
.unwrap_or(false)
} Try / catch
let result = std::panic::catch_unwind(|| load_debloat_lists());
if result.is_err() {
eprintln!("Unable to write file — check cache dir permissions/disk space");
} Prevention
- Ensure setup_uad_dir runs successfully before any cache write
- Point the cache at a user-writable directory
- Keep free disk space on the cache volume
- Exclude the cache dir from aggressive antivirus file locks
When it happens
Trigger: CACHE_DIR/uad (cache directory) does not exist or is unwritable when load_debloat_lists runs; disk full; antivirus/OS locking the file on Windows.
Common situations: First run where setup_uad_dir failed or was skipped; user cache dir redirected to a read-only location; low disk space; AppArmor/sandbox blocking the cache path.
Understand the failure class
Background: "Permission denied" / "Failed to write" file errors: why a library can't write its files to disk (EACCES, EPERM, ENOSPC) and how to fix them — this error's family across 43 libraries.
Related errors
- Can't create cache directory
- Could not write config file to disk!
- Unable to parse backup file
- response should be Ok type
- Unable to parse
AI-assisted analysis of 0x192/universal-android-debloater@11f27c671c (2026-09-02).
Data as JSON: /api/errors/535341e97b3ee893.
Report an issue: GitHub.