{"record":{"id":"749e61e752b85c6e","repo":"MuntashirAkon/AppManager","slug":"couldn-t-verify-metadata-file-nfile-metadatafile-nfound","errorCode":null,"errorMessage":"Couldn't verify metadata file.\\nFile: \" + metadataFile + \"\\nFound: \" + checksum + \"\\nRequired: \" + mChecksum.get(metadataFile.getName())","messagePattern":"Couldn't verify metadata file\\.\\\\nFile: \" \\+ metadataFile \\+ \"\\\\nFound: \" \\+ checksum \\+ \"\\\\nRequired: \" \\+ mChecksum\\.get\\(metadataFile\\.getName\\(\\)\\)","errorType":"exception","errorClass":"BackupException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/backup/VerifyOp.java","lineNumber":132,"sourceCode":"                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        }\n    }\n\n    private void verifyApkFiles() throws BackupException {\n        Path[] backupSourceFiles = mBackupItem.getSourceFiles();\n        if (backupSourceFiles.length == 0) {\n            // No APK files found\n            throw new BackupException(\"Backup does not contain any APK files.\");\n        }\n        String checksum;\n        for (Path file : backupSourceFiles) {\n            checksum = DigestUtils.getHexDigest(mBackupInfo.checksumAlgo, file);\n            if (!checksum.equals(mChecksum.get(file.getName()))) {\n                throw new BackupException(\"Could not verify APK files.\" +\n                        \"\\nFile: \" + file.getName() +","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/backup/VerifyOp.java#L114-L150","documentation":"verifyMetadata() recomputes the digest of the metadata file (v5 metadata or v2 metadata depending on backup format) and it does not match the digest stored in the backup's checksum file. The metadata content differs from what was recorded at backup time, so App Manager refuses to trust it.","triggerScenarios":"VerifyOp constructor -> verifyMetadata(); DigestUtils.getHexDigest(mBackupInfo.checksumAlgo, metadataFile) != mChecksum.get(metadataFile.getName()), including when the checksum file lacks an entry for the metadata file name (null required value).","commonSituations":"Metadata file edited manually (e.g. changing versionName or flags) without updating checksums; partial download/transfer that altered the file; a checksum file from a different backup paired with this metadata; checksumAlgo mismatch between what was recorded and how the file is hashed.","solutions":["Compare the 'Found' and 'Required' digests in the message against the file to confirm which one is stale; recompute with the recorded algo (sha256sum etc.).","Restore the original, unmodified metadata file (re-copy the backup from its source).","If the edit was intentional, recompute the metadata digest and update the checksum file entry.","Recreate the backup if the original is unavailable."],"exampleFix":"// before\n//   Couldn't verify metadata file. Found: abc123... Required: def456...\n// after: regenerate the checksum file entry for the (edited) metadata file\n// $ sha256sum <metadata-file>  -> update entry in backup.checksums","handlingStrategy":"validation","validationCode":"// Pre-check metadata integrity outside the library\nPath metadataFile = isV5AndUp ? backupItem.getMetadataV5File(false) : backupItem.getMetadataV2File();\nString found = DigestUtils.getHexDigest(backupInfo.checksumAlgo, metadataFile);\nif (!found.equals(checksums.get(metadataFile.getName()))) {\n    throw new IllegalStateException(\"metadata checksum mismatch: re-copy or regenerate checksums\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    new VerifyOp(backupItem);\n} catch (BackupException e) {\n    if (e.getMessage().startsWith(\"Couldn't verify metadata file\")) {\n        // compare Found vs Required; restore original metadata or update checksum entry\n    }\n}","preventionTips":["Treat backup directories as immutable; copy instead of editing in place.","After any intentional metadata edit, recompute the digest and update the checksum file in the same step.","Pair each metadata file only with the checksum file from the same backup run.","Run a verify pass immediately after backup creation and again after each transfer."],"tags":["backup","integrity","checksum","metadata"],"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"}