{"record":{"id":"627b8d4c5aff23ae","repo":"MuntashirAkon/AppManager","slug":"could-not-retrieve-metadata-from-backup","errorCode":null,"errorMessage":"Could not retrieve metadata from backup.","messagePattern":"Could not retrieve metadata from backup\\.","errorType":"exception","errorClass":"BackupException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/backup/BackupManager.java","lineNumber":156,"sourceCode":"                    throw new BackupException(\"Could not get backup files.\", e);\n                }\n            } else backupItemList = Collections.emptyList();\n        } else {\n            backupItemList = new ArrayList<>(options.relativeDirs.length);\n            for (String relativeDir : options.relativeDirs) {\n                try {\n                    backupItemList.add(BackupItems.findBackupItem(relativeDir));\n                } catch (IOException e) {\n                    throw new BackupException(\"Could not get backup files.\", e);\n                }\n            }\n        }\n        for (BackupItems.BackupItem backupItem : backupItemList) {\n            BackupMetadataV5 metadata;\n            try {\n                metadata = backupItem.getMetadata();\n            } catch (IOException e) {\n                throw new BackupException(\"Could not retrieve metadata from backup.\", e);\n            }\n            if (!backupItem.isFrozen() && !backupItem.delete()) {\n                throw new BackupException(\"Could not delete the selected backups\");\n            }\n            BackupUtils.deleteBackupToDbAndBroadcast(ContextUtils.getContext(), metadata);\n        }\n    }\n\n    public void verify(@NonNull String relativeDir) throws BackupException {\n        BackupItems.BackupItem backupItem;\n        try {\n            backupItem = BackupItems.findBackupItem(relativeDir);\n        } catch (IOException e) {\n            throw new BackupException(\"Could not get backup files.\", e);\n        }\n        try (VerifyOp restoreOp = new VerifyOp(backupItem)) {\n            restoreOp.verify();\n        }","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/backup/BackupManager.java#L138-L174","documentation":"In deleteBackup(), after resolving each BackupItem, its metadata is read via backupItem.getMetadata(); an IOException is rethrown as BackupException('Could not retrieve metadata from backup.', e). This means the backup directory exists but its metadata file (e.g. the .backup-metadata or versioned metadata file) is missing or unreadable.","triggerScenarios":"deleteBackup() on a backup directory whose metadata file is absent, corrupted, or on unreadable storage — thrown from the getMetadata() call in the delete loop.","commonSituations":"Partial/aborted backup leaves a directory without metadata; cleaner apps deleted the metadata file; corrupted external storage; manually copied backup dirs that lost hidden/metadata files.","solutions":["Inspect the backup directory for the metadata file and restore it from a full copy of the backup.","If metadata is unrecoverable, delete the directory manually (file manager/root) instead of via deleteBackup(), then prune the DB entry.","Re-run the backup to regenerate a valid directory, then delete it cleanly.","Catch BackupException and check getCause() to identify the corrupt path."],"exampleFix":"// before\nmetadata = backupItem.getMetadata(); // throws if metadata file missing\n// after\ntry {\n    metadata = backupItem.getMetadata();\n} catch (IOException e) {\n    // fall back to manual removal\n    new File(backupRoot, relativeDir).deleteRecursively();\n    return;\n}","handlingStrategy":"try-catch","validationCode":"File meta = new File(backupRoot, relDir, \".backup-metadata\"); // version-appropriate name\nif (!meta.exists()) {\n    throw new IllegalStateException(\"Metadata missing for \" + relDir);\n}","typeGuard":"boolean hasMetadata(String relDir) {\n    File d = new File(backupRoot, relDir);\n    return d.isDirectory() && Objects.requireNonNull(d.list()).length > 1;\n}","tryCatchPattern":"try {\n    manager.deleteBackup(options);\n} catch (BackupException e) {\n    if (e.getMessage().contains(\"metadata\")) {\n        // metadata corrupt: remove dir manually + prune DB\n    }\n}","preventionTips":["Avoid interrupting backups mid-write; check completion status before deleting","Exclude backup dirs from cleaner apps","Restore metadata from a full backup copy when available"],"tags":["android","backup","delete","metadata","io"],"backgroundTag":"file-read-failed","analyzedSha":"0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5","analyzedAt":"2026-09-12T14:03:37.243Z","contentChangedAt":"2026-09-12T14:03:37.243Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}