Universal-Debloater-Alliance/universal-android-debloater-next-generation · error
Unable to parse backup file
Error message
Unable to parse backup file
What it means
list_available_backup_user reads a backup file and deserializes it into PhoneBackup with serde_json; malformed JSON panics with "Unable to parse backup file". The library assumes any selected .backup/.json file is a valid UAD phone backup.
Solutions
- Validate the file with a JSON linter or `jq . file` to confirm it parses.
- Confirm the backup was exported by a compatible UAD version (PhoneBackup schema).
- Re-export the backup from the original device.
- Wrap parsing with serde_json::from_str(...).ok()/Result handling and show a user-facing error instead of panicking.
Example fix
// before
serde_json::from_str::<PhoneBackup>(&data).expect("Unable to parse backup file")
// after
let phone_backup: PhoneBackup = serde_json::from_str(&data)
.map_err(|e| error!("Unable to parse backup file: {e}")).unwrap_or_default(); Defensive patterns
Strategy: validation
Validate before calling
fn is_valid_uad_backup(path: &std::path::Path) -> bool {
std::fs::read_to_string(path)
.ok()
.and_then(|s| serde_json::from_str::<serde_json::Value>(&s).ok())
.map(|v| v.get("users").is_some())
.unwrap_or(false)
} Type guard
fn is_phone_backup(v: &serde_json::Value) -> bool {
v.get("users").and_then(|u| u.as_array()).map(|a| a.iter().all(|x| x.get("id").is_some())).unwrap_or(false)
} Try / catch
match std::fs::read_to_string(backup.path) {
Ok(data) => match serde_json::from_str::<PhoneBackup>(&data) {
Ok(pb) => { /* use pb.users */ }
Err(e) => eprintln!("Unable to parse backup file: {e}"),
},
Err(e) => eprintln!("read failed: {e}"),
} Prevention
- Only select backups exported by a compatible UAD version.
- Validate JSON with `jq .` before importing.
- Never hand-edit backup files without re-validating.
- Check UTF-8 encoding and absence of BOM/UTF-16.
When it happens
Trigger: Calling list_available_backup_user(backup) with a file that is not valid JSON, is an older/incompatible backup schema, is empty, or has a different encoding (UTF-16/BOM).
Common situations: User selects a random or renamed file in the restore dialog; backups exported by an older UAD version with a changed PhoneBackup schema; truncated downloads.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Unable to parse
- {e}
- There must be 1 tab after serial
- There must be at least 1 ':'-separated component
- string assumed to be UID numeral
AI-assisted analysis of Universal-Debloater-Alliance/universal-android-debloater-next-generation@64465c850c (2026-09-12).
Data as JSON: /api/errors/5c8a8b6cc88fbab3.
Report an issue: GitHub.
Appendix: source
Thrown at crates/uad-core/src/save.rs:82
Err(err) => Err(err.to_string()),
}
}
pub fn list_available_backups(dir: &Path) -> Vec<DisplayablePath> {
match fs::read_dir(dir) {
Ok(files) => files
.filter_map(Result::ok)
.map(|e| DisplayablePath { path: e.path() })
.collect::<Vec<_>>(),
Err(_) => vec![],
}
}
#[must_use]
pub fn list_available_backup_user(backup: DisplayablePath) -> Vec<User> {
match fs::read_to_string(backup.path) {
Ok(data) => serde_json::from_str::<PhoneBackup>(&data)
.expect("Unable to parse backup file")
.users
.into_iter()
.map(|u| User {
id: u.id,
index: 0,
protected: false,
})
.collect(),
Err(e) => {
error!("[BACKUP]: Selected backup file not found: {e}");
vec![]
}
}
}
#[derive(Debug)]
pub struct BackupPackage {
pub i_user: usize,View on GitHub (pinned to 64465c850c)