{"record":{"id":"cb880c4ee0d1d984","repo":"MuntashirAkon/AppManager","slug":"couldn-t-verify-metadata-file","errorCode":null,"errorMessage":"Couldn't verify metadata file.","messagePattern":"Couldn't verify metadata file\\.","errorType":"exception","errorClass":"BackupException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/backup/RestoreOp.java","lineNumber":230,"sourceCode":"        progressHandler.postUpdate(current);\n    }\n\n    public boolean requiresRestart() {\n        return mRequiresRestart;\n    }\n\n    private void verifyMetadata() throws BackupException {\n        boolean isV5AndUp = mBackupItem.isV5AndUp();\n        if (isV5AndUp) {\n            Path infoFile;\n            try {\n                infoFile = mBackupItem.getInfoFile();\n            } catch (IOException e) {\n                throw new BackupException(\"Could not get metadata file.\", e);\n            }\n            String checksum = DigestUtils.getHexDigest(mBackupInfo.checksumAlgo, infoFile);\n            if (!checksum.equals(mChecksum.get(infoFile.getName()))) {\n                throw new BackupException(\"Couldn't verify metadata file.\" +\n                        \"\\nFile: \" + infoFile +\n                        \"\\nFound: \" + checksum +\n                        \"\\nRequired: \" + mChecksum.get(infoFile.getName()));\n            }\n        }\n        Path metadataFile;\n        try {\n            metadataFile = isV5AndUp ? mBackupItem.getMetadataV5File(false) : mBackupItem.getMetadataV2File();\n        } catch (IOException e) {\n            throw new BackupException(\"Could not get metadata file.\", e);\n        }\n        String checksum = DigestUtils.getHexDigest(mBackupInfo.checksumAlgo, metadataFile);\n        if (!checksum.equals(mChecksum.get(metadataFile.getName()))) {\n            throw new BackupException(\"Couldn't verify metadata file.\" +\n                    \"\\nFile: \" + metadataFile +\n                    \"\\nFound: \" + checksum +\n                    \"\\nRequired: \" + mChecksum.get(metadataFile.getName()));\n        }","sourceCodeStart":212,"sourceCodeEnd":248,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/backup/RestoreOp.java#L212-L248","documentation":"verifyMetadata digests backup.json with mBackupInfo.checksumAlgo and compares it to the recorded checksum; on mismatch it throws BackupException 'Couldn't verify metadata file.' with file, found, and required values. This means the backup info file changed after the backup was signed/recorded.","triggerScenarios":"DigestUtils.getHexDigest(infoFile) != mChecksum.get(infoFile.getName()) — backup.json was modified, re-encoded, or truncated after checksums were computed, or the wrong checksum algo is recorded in backup.json.","commonSituations":"User hand-edited backup.json (e.g. changed label or flags) before restoring; transfer mangled the file (line-ending or encoding changes); backup created by an older app version using a different algorithm.","solutions":["Restore the original unmodified backup.json that matches checksums.txt","If you must change backup.json, re-create the backup (or recompute checksums) so the manifest matches","Compare the 'Found' vs 'Required' digests in the message to confirm the file really differs","Verify mBackupInfo.checksumAlgo matches the algorithm used to generate the manifest"],"exampleFix":"// before\nif (!checksum.equals(mChecksum.get(infoFile.getName()))) {\n    throw new BackupException(\"Couldn't verify metadata file.\\nFile: \" + infoFile + ...);\n}\n// after\n// no code fix: restore pristine backup.json, or regenerate the checksum manifest\n// e.g. recompute: checksums.txt entry for backup.json = digester(infoFile)","handlingStrategy":"validation","validationCode":"// pre-check: recompute digest of backup.json and compare with the manifest entry\nString found = DigestUtils.getHexDigest(info.checksumAlgo, infoFile);\nif (!found.equals(checksums.get(infoFile.getName()))) throw new BackupException(\"backup.json was modified after backup\");","typeGuard":null,"tryCatchPattern":"try { restoreOp.runRestore(handler); } catch (BackupException e) { if (e.getMessage().startsWith(\"Couldn't verify metadata file.\")) { showFoundVsRequiredDialog(e.getMessage()); } throw e; }","preventionTips":["Treat backup.json as immutable after creation","If flags/labels must change, regenerate the backup (and its checksums)","Transfer backups in binary-safe modes; avoid tools that rewrite line endings"],"tags":["checksum","integrity","backup","tampering"],"backgroundTag":"checksum-mismatch","analyzedSha":"0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5","analyzedAt":"2026-09-12T14:03:37.243Z","contentChangedAt":"2026-09-12T14:03:37.243Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}