{"record":{"id":"f6003aaa8a74be9b","repo":"MuntashirAkon/AppManager","slug":"could-not-finalise-backup","errorCode":null,"errorMessage":"Could not finalise backup.","messagePattern":"Could not finalise backup\\.","errorType":"exception","errorClass":"BackupException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/backup/BackupOp.java","lineNumber":206,"sourceCode":"                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        }\n        float current = progressHandler.getLastProgress() + 1;\n        progressHandler.postUpdate(current);\n    }\n\n    public BackupMetadataV5 setupMetadataAndCrypto() throws CryptoException {\n        // We don't need to backup custom users or multiple backup flags","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/backup/BackupOp.java#L188-L224","documentation":"The final step of runBackup() replaces the previous backup with the newly assembled one via mBackupItem.commit(); an IOException there is wrapped in this BackupException. All backup content was created (and encrypted) but the atomic swap into the final backup directory failed, leaving the old backup untouched.","triggerScenarios":"mBackupItem.commit() throws IOException while renaming/moving the staged backup files into the committed backup location.","commonSituations":"Destination filesystem doesn't support atomic rename across mount points; storage full; the existing backup directory is locked or on read-only media; SAF provider refused the move.","solutions":["Check free space and mount status of the backup volume.","Ensure the old backup directory isn't open/locked by another process (e.g. a file manager over SAF).","Remove the stale previous backup manually and retry.","Back up to a local storage path rather than cross-device SAF locations."],"exampleFix":"// before\nbackupPath = new UriPath(\"content://com.android.externalstorage.document/tree/primary.../backup\"); // slow SAF\n// after\nbackupPath = new LocalPath(\"/sdcard/AppManager/backup\"); // direct FS, commit works","handlingStrategy":"try-catch","validationCode":"if (!backupDest.canWrite() || backupDest.getUsableSpace() < 100*1024*1024) { throw new IOException(\"Cannot finalise: destination unusable\"); }","typeGuard":null,"tryCatchPattern":"try {\n    backupOp.runBackup(progress);\n} catch (BackupException e) {\n    if (e.getMessage().equals(\"Could not finalise backup.\")) {\n        // old backup still intact; clean staged files and retry\n        deleteStagedBackupFiles();\n    }\n}","preventionTips":["Avoid cross-filesystem destinations that break atomic rename.","Close file managers holding the backup dir open via SAF.","Free space before running backups of large apps.","Manually remove stale prior backups if commit repeatedly fails."],"tags":["android","backup","io","commit"],"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-23T08:17:48.524Z"}