{"record":{"id":"d789591df30725e7","repo":"MuntashirAkon/AppManager","slug":"mode","errorCode":null,"errorMessage":"Mode ","messagePattern":"Mode ","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/backup/MetadataManager.java","lineNumber":162,"sourceCode":"        }\n        // Encrypt the metadata\n        Path encryptedMetadataFile = backupFile.encrypt(new Path[]{metadataFile})[0];\n        filenameChecksumMap.put(encryptedMetadataFile.getName(), DigestUtils.getHexDigest(\n                metadata.info.checksumAlgo, encryptedMetadataFile));\n        Path infoFile = backupFile.getInfoFile();\n        try (OutputStream outputStream = infoFile.openOutputStream()) {\n            outputStream.write(metadata.info.serializeToJson().toString(4).getBytes());\n            filenameChecksumMap.put(infoFile.getName(), DigestUtils.getHexDigest(\n                    metadata.info.checksumAlgo, infoFile));\n        } catch (JSONException e) {\n            throw new IOException(e.getMessage() + \" for file \" + infoFile, e);\n        }\n        return filenameChecksumMap;\n    }\n\n    private static void setCrypto(@NonNull BackupItems.BackupItem backupItem, @NonNull BackupMetadataV5.Info backupInfo) throws IOException {\n        if (!CryptoUtils.isAvailable(backupInfo.crypto)) {\n            throw new IOException(\"Mode \" + backupInfo.crypto + \" is currently unavailable.\");\n        }\n        try {\n            backupItem.setCrypto(backupInfo.getCrypto());\n        } catch (CryptoException e) {\n            throw new IOException(\"Failed to get crypto \" + backupInfo.crypto, e);\n        }\n    }\n}\n","sourceCodeStart":144,"sourceCodeEnd":171,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/backup/MetadataManager.java#L144-L171","documentation":"setCrypto validates that the crypto mode stored in the backup's info (e.g. a specific encryption scheme) is available in the current environment via CryptoUtils.isAvailable, throwing IOException when it is not. This prevents attempting decryption with an unavailable algorithm/provider.","triggerScenarios":"readMetadata encountering a backup whose info specifies a crypto mode not supported on this device/build — e.g. backups encrypted with a keystore-bound or device-specific scheme being opened elsewhere.","commonSituations":"Restoring a backup on a different device or after a ROM change where the original crypto provider (e.g. RSA keys in a hardware keystore) no longer exists; backups made with a master-key/keystore option then opened without the key.","solutions":["Configure the crypto mode used by the backup (e.g. provide the correct key/password via CryptoUtils setup) before reading metadata.","If the original key is gone (hardware keystore), the backup cannot be decrypted on this device — restore it on the original device.","Check CryptoUtils.getMode availability and pick a supported mode for new backups to keep them portable."],"exampleFix":"// before\nBackupMetadataV5 meta = MetadataManager.readMetadata(backupItem);\n// after\nString mode = MetadataManager.getInfo(backupItem).crypto;\nif (!CryptoUtils.isAvailable(mode)) {\n    throw new IOException(\"Crypto mode \" + mode + \" is unavailable on this device\");\n}\nBackupMetadataV5 meta = MetadataManager.readMetadata(backupItem);","handlingStrategy":"validation","validationCode":"String mode = backupInfo.crypto;\nif (!CryptoUtils.isAvailable(mode)) {\n    throw new IOException(\"Crypto mode \" + mode + \" unavailable; configure keys or use the original device\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    BackupMetadataV5 meta = MetadataManager.readMetadata(backupItem);\n} catch (IOException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Mode \")) {\n        // prompt user to provide decryption credentials or restore on the original device\n    } else throw e;\n}","preventionTips":["Prefer portable crypto modes (e.g. password-based) over keystore-bound ones for backups you may restore elsewhere.","Check CryptoUtils availability before creating encrypted backups.","Keep decryption credentials/key stores backed up separately from device-bound keys."],"tags":["backup","encryption","crypto","unsupported"],"backgroundTag":"unsupported-operation","analyzedSha":"0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5","analyzedAt":"2026-09-12T14:03:37.243Z","contentChangedAt":"2026-09-12T14:03:37.243Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}