{"record":{"id":"49da1d6f66577b1b","repo":"MuntashirAkon/AppManager","slug":"failed-to-write-checksums-txt","errorCode":null,"errorMessage":"Failed to write checksums.txt","messagePattern":"Failed to write checksums\\.txt","errorType":"exception","errorClass":"BackupException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/backup/BackupOp.java","lineNumber":200,"sourceCode":"            if (mMetadata.metadata.hasRules) {\n                backupRules();\n                incrementProgress(progressHandler);\n            }\n            // Write modified metadata\n            try {\n                Map<String, String> filenameChecksumMap = MetadataManager.writeMetadata(mMetadata, mBackupItem);\n                for (Map.Entry<String, String> entry : filenameChecksumMap.entrySet()) {\n                    mChecksum.add(entry.getKey(), entry.getValue());\n                }\n            } catch (IOException e) {\n                throw new BackupException(\"Failed to write metadata.\", e);\n            }\n            mChecksum.close();\n            // Encrypt checksum\n            try {\n                mBackupItem.encrypt(new Path[]{mChecksum.getFile()});\n            } catch (IOException e) {\n                throw new BackupException(\"Failed to write checksums.txt\", e);\n            }\n            // Replace current backup\n            try {\n                mBackupItem.commit();\n            } catch (IOException e) {\n                throw new BackupException(\"Could not finalise backup.\", e);\n            }\n        } catch (BackupException e) {\n            throw e;\n        } catch (Throwable th) {\n            throw new BackupException(\"Unknown error occurred.\", th);\n        }\n    }\n\n    private static void incrementProgress(@Nullable ProgressHandler progressHandler) {\n        if (progressHandler == null) {\n            return;\n        }","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/backup/BackupOp.java#L182-L218","documentation":"After closing the checksum writer, BackupOp encrypts checksums.txt when encryption is enabled; an IOException from mBackupItem.encrypt() is wrapped in this BackupException. The checksum file exists but could not be encrypted into the final backup, so the backup set is incomplete and not committed.","triggerScenarios":"Encryption is enabled for the backup and mBackupItem.encrypt(new Path[]{mChecksum.getFile()}) throws IOException — bad crypto setup, missing output stream, or storage failure.","commonSituations":"Wrong/changed backup encryption password or keystore; encrypted-backup prerequisites (root, crypto provider) unavailable; destination storage full while writing the encrypted copy.","solutions":["Verify the backup encryption password/keystore is correct and crypto providers are available (crypto needs root).","Check free space on the destination.","Inspect the chained IOException for the underlying crypto/I/O cause.","Retry the backup; the old backup is not committed so no corruption occurs."],"exampleFix":"// before\nCryptoUtils.setupPassword(Prefs.EncryptionMode.DEFAULT, password); // wrong/mistyped password\n// after\nbyte[] keystore = CryptoUtils.getKeystore(CryptoUtils.KeyStoreMode.RAW); // verify crypto is available\nCryptoUtils.setupPassword(Prefs.EncryptionMode.DEFAULT, verifiedPassword);","handlingStrategy":"try-catch","validationCode":"if (Prefs.Crypto.isEncryptionEnabled()) { /* verify password works before running backup */ CryptoUtils.decryptTestBlob(savedBlob, password); }","typeGuard":"boolean encryptionReady() { return !Prefs.Crypto.isEncryptionEnabled() || CryptoUtils.canAccessKeystore(); }","tryCatchPattern":"try {\n    backupOp.runBackup(progress);\n} catch (BackupException e) {\n    if (e.getMessage().equals(\"Failed to write checksums.txt\")) {\n        Log.e(TAG, \"checksum encryption failed\", (IOException) e.getCause());\n    }\n}","preventionTips":["Confirm the backup password/keystore before long backup jobs.","Ensure root is available when encrypted backups are enabled.","Keep enough free space for encrypted duplicates of all artifacts.","Note the previous backup is left intact — safe to retry."],"tags":["android","backup","encryption","io"],"backgroundTag":"file-write-failed","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"}