Universal-Debloater-Alliance/universal-android-debloater-next-generation · critical
Could not write config file to disk!
Error message
Could not write config file to disk!
What it means
save_device_settings serializes the whole config to TOML and writes it to CONFIG_FILE; if fs::write fails it panics with "Could not write config file to disk!". The library treats inability to persist settings as a hard failure, raised on every settings-mutating handler.
Solutions
- Check write permissions on the config directory and file (ls -l, try touching the file as the same user).
- Free disk space / check quota.
- If sandboxed (flatpak, snap), grant access to the config path or set a writable XDG_CONFIG_HOME.
- Wrap the save call in catch_unwind or patch to return Result and surface a UI error instead of panicking.
Example fix
// before
fs::write(&*CONFIG_FILE, toml).expect("Could not write config file to disk!");
// after
if let Err(e) = fs::write(&*CONFIG_FILE, toml) {
error!("Could not write config file: {e}");
return; // or propagate a Result::Err to the caller
} Defensive patterns
Strategy: validation
Validate before calling
let cfg_dir = config_file.parent().unwrap_or(std::path::Path::new("."));
if !cfg_dir.is_dir() { return Err("config dir missing"); }
let probe = cfg_dir.join(".write_test");
std::fs::write(&probe, b"").map_err(|e| format!("config dir not writable: {e}"))?;
let _ = std::fs::remove_file(&probe); Type guard
fn config_writable(p: &std::path::Path) -> bool {
if let Some(d) = p.parent() { d.is_dir() && std::fs::OpenOptions::new().append(true).open(p).or_else(|_| std::fs::OpenOptions::new().write(true).create_new(true).open(d.join(".probe"))).is_ok() } else { false }
} Try / catch
std::panic::catch_unwind(|| config.save_device_settings(general, device_settings))
.map_err(|_| "could not write config file to disk")?; Prevention
- Check disk space and write permissions on the config directory regularly.
- In flatpak/snap, grant the app access to its config path.
- Avoid running the app as a user without a writable HOME.
- Prefer a Result-returning save API and surface errors in the UI.
When it happens
Trigger: Calling save_device_settings (via handle_expert_mode, handle_disable_mode, handle_multi_user_mode, handle_apply_theme, handle_folder_chosen) when CONFIG_FILE cannot be written: parent dir missing/locked, read-only filesystem, disk full, or permission denied.
Common situations: Read-only $HOME, flatpak/sandbox blocking the config path, another process holding a mandatory lock, quota exceeded, or CONFIG_DIR setup previously failed.
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
- {e}
- Can't detect config dir
- There must be 1 tab after serial
- 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/5e49276c44f3b986.
Report an issue: GitHub.
Appendix: source
Thrown at crates/uad-core/src/config.rs:75
impl Config {
pub fn save_device_settings(
&mut self,
device_settings: DeviceSettings,
general: GeneralSettings,
) {
if let Some(device) = self
.devices
.iter_mut()
.find(|x| x.device_id == device_settings.device_id)
{
*device = device_settings;
} else {
self.devices.push(device_settings);
}
self.general = general;
let toml = toml::to_string(&self).unwrap();
fs::write(&*CONFIG_FILE, toml).expect("Could not write config file to disk!");
}
#[must_use]
pub fn load_configuration_file() -> Self {
match fs::read_to_string(&*CONFIG_FILE) {
Ok(s) => match toml::from_str(&s) {
Ok(config) => return config,
Err(e) => error!("Invalid config file: `{e}`"),
},
Err(e) => error!("Failed to read config file: `{e}`"),
}
error!("Restoring default config file");
let toml = toml::to_string(&Self::default()).unwrap();
fs::write(&*CONFIG_FILE, toml).expect("Could not write config file to disk!");
Self::default()
}
}
View on GitHub (pinned to 64465c850c)