{"record":{"id":"9e95df9f73c5a34e","repo":"MuntashirAkon/AppManager","slug":"failed-to-write-metadata","errorCode":null,"errorMessage":"Failed to write metadata.","messagePattern":"Failed to write metadata\\.","errorType":"exception","errorClass":"BackupException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/backup/BackupOp.java","lineNumber":193,"sourceCode":"            }\n            // Backup extras\n            if (mBackupFlags.backupExtras()) {\n                backupExtras();\n                incrementProgress(progressHandler);\n            }\n            // Export rules\n            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);","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/backup/BackupOp.java#L175-L211","documentation":"BackupOp wraps IOException from MetadataManager.writeMetadata() in a BackupException with this message. The metadata file (containing backup flags, version codes, timestamps, checksums) could not be serialized and written into the backup directory. Without it the backup cannot be restored, so the whole operation fails.","triggerScenarios":"MetadataManager.writeMetadata(mMetadata, mBackupItem) throws IOException while creating or writing the metadata JSON file into the backup item's storage.","commonSituations":"Backup destination is full or read-only (external SD card, SAF document provider denied write); the backup directory was deleted mid-operation; disk I/O errors.","solutions":["Verify free space on the backup storage volume.","Confirm the backup destination path is writable (re-grant SAF/storage permissions).","Check the chained IOException's message for the exact path and reason.","Delete any partially written backup directory and retry the backup."],"exampleFix":"// before\nmBackupItem = new BackupItems(...); // writes to stale SAF dir\n// after\nif (!mBackupItem.getUnencryptedBackupPath().canWrite()) {\n    throw new IOException(\"Backup destination not writable\"); // fix permissions first\n}","handlingStrategy":"try-catch","validationCode":"if (backupDest.getUsableSpace() < 100*1024*1024 || !backupDest.canWrite()) { throw new IOException(\"Destination not writable or full\"); }","typeGuard":"boolean isWritableDir(Path p) { return p != null && p.isDirectory() && p.canWrite(); }","tryCatchPattern":"try {\n    backupOp.runBackup(progress);\n} catch (BackupException e) {\n    if (e.getMessage().equals(\"Failed to write metadata.\")) {\n        Log.e(TAG, \"metadata write failed\", (IOException) e.getCause());\n    }\n}","preventionTips":["Check free space and write permissions on the backup volume first.","Re-grant SAF/storage permissions after OS updates.","Don't delete the backup directory while a backup is running.","Use local storage paths instead of unreliable document-provider URIs."],"tags":["android","backup","io","metadata"],"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"}