{"record":{"id":"fee60866afbeb7ce","repo":"MuntashirAkon/AppManager","slug":"source-file-verification-failed-nfile-file-nfound-checksum","errorCode":null,"errorMessage":"Source file verification failed.\\nFile: ${file}\\nFound: ${checksum}\\nRequired: ${mChecksum.get(file.getName())}","messagePattern":"Source file verification failed\\.\\\\nFile: (.+?)\\\\nFound: (.+?)\\\\nRequired: (.+?)","errorType":"exception","errorClass":"BackupException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/backup/RestoreOp.java","lineNumber":303,"sourceCode":"            // Check signature of the installed app\n            List<String> certChecksumList = Arrays.asList(PackageUtils.getSigningCertChecksums(mBackupInfo.checksumAlgo, mPackageInfo, false));\n            String[] certChecksums = BackupItems.Checksum.getCertChecksums(mChecksum);\n            for (String checksum : certChecksums) {\n                if (certChecksumList.contains(checksum)) continue;\n                isVerified = false;\n                if (!mRequestedFlags.skipSignatureCheck()) {\n                    throw new BackupException(\"Signing info verification failed.\" +\n                            \"\\nInstalled: \" + certChecksumList +\n                            \"\\nBackup: \" + Arrays.toString(certChecksums));\n                }\n            }\n        }\n        if (!mRequestedFlags.skipSignatureCheck()) {\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(\"Source file verification failed.\" +\n                            \"\\nFile: \" + file +\n                            \"\\nFound: \" + checksum +\n                            \"\\nRequired: \" + mChecksum.get(file.getName()));\n                }\n            }\n        }\n        if (!isVerified) {\n            // Signature verification failed but still here because signature check is disabled.\n            // The only way to restore is to reinstall the app\n            synchronized (sLock) {\n                PackageInstallerCompat installer = PackageInstallerCompat.getNewInstance();\n                if (installer.uninstall(mPackageName, mUserId, false)) {\n                    throw new BackupException(\"An uninstallation was necessary but couldn't perform it.\");\n                }\n            }\n        }\n        // Setup package staging directory\n        Path packageStagingDirectory = Paths.get(PackageUtils.PACKAGE_STAGING_DIRECTORY);","sourceCodeStart":285,"sourceCodeEnd":321,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/backup/RestoreOp.java#L285-L321","documentation":"As part of restoreApkFiles(), each backed-up source file is hashed with the backup's checksum algorithm and compared with the checksum recorded in the checksum file. Any divergence aborts the restore with this BackupException, protecting against corrupted or tampered APK archives. Message includes the file path, computed checksum, and required checksum.","triggerScenarios":"For a file in backupSourceFiles, DigestUtils.getHexDigest(mBackupInfo.checksumAlgo, file) != mChecksum.get(file.getName()) while skipSignatureCheck() is false.","commonSituations":"Incomplete/corrupted transfer of the backup folder (cloud sync truncation, bad SD card); backup files modified after creation; wrong checksums file placed alongside the backup; checksum algorithm changed between backup and restore.","solutions":["Re-copy the backup set from its original source and retry; the failing file is likely truncated or corrupted.","Verify storage media health (SD card errors are a common cause) and free space at the destination.","If you intentionally modified a source file, recompute its checksum and update the checksums file with the same algorithm.","Confirm the checksums file corresponds to this backup; restore the correct one if backup sets were mixed."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Pre-verify every source file before restore:\nfor (Path f : backupItem.getSourceFiles()) {\n    String found = DigestUtils.getHexDigest(info.checksumAlgo, f);\n    if (!found.equals(checksums.get(f.getName()))) {\n        // re-copy the corrupted file before invoking restore\n    }\n}","typeGuard":null,"tryCatchPattern":"try { restoreOp.runRestore(); } catch (BackupException e) {\n    if (e.getMessage().startsWith(\"Source file verification failed\")) {\n        // extract File/Found/Required from message; re-transfer that file\n    }\n}","preventionTips":["Verify checksums after copying backups across devices or cloud storage.","Watch storage health (SD card wear) and retry failed transfers.","Keep the checksums file paired with its exact backup set."],"tags":["android","backup","integrity-check","checksum"],"backgroundTag":"checksum-mismatch","analyzedSha":"0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5","analyzedAt":"2026-09-12T14:03:37.243Z","contentChangedAt":"2026-09-12T14:03:37.243Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}