MuntashirAkon/AppManager · error · IOException

Mode

Error message

Mode 

What it means

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.

Source

Thrown at app/src/main/java/io/github/muntashirakon/AppManager/backup/MetadataManager.java:162

        }
        // Encrypt the metadata
        Path encryptedMetadataFile = backupFile.encrypt(new Path[]{metadataFile})[0];
        filenameChecksumMap.put(encryptedMetadataFile.getName(), DigestUtils.getHexDigest(
                metadata.info.checksumAlgo, encryptedMetadataFile));
        Path infoFile = backupFile.getInfoFile();
        try (OutputStream outputStream = infoFile.openOutputStream()) {
            outputStream.write(metadata.info.serializeToJson().toString(4).getBytes());
            filenameChecksumMap.put(infoFile.getName(), DigestUtils.getHexDigest(
                    metadata.info.checksumAlgo, infoFile));
        } catch (JSONException e) {
            throw new IOException(e.getMessage() + " for file " + infoFile, e);
        }
        return filenameChecksumMap;
    }

    private static void setCrypto(@NonNull BackupItems.BackupItem backupItem, @NonNull BackupMetadataV5.Info backupInfo) throws IOException {
        if (!CryptoUtils.isAvailable(backupInfo.crypto)) {
            throw new IOException("Mode " + backupInfo.crypto + " is currently unavailable.");
        }
        try {
            backupItem.setCrypto(backupInfo.getCrypto());
        } catch (CryptoException e) {
            throw new IOException("Failed to get crypto " + backupInfo.crypto, e);
        }
    }
}

View on GitHub (pinned to 0152f468fc)

Solutions

  1. Configure the crypto mode used by the backup (e.g. provide the correct key/password via CryptoUtils setup) before reading metadata.
  2. If the original key is gone (hardware keystore), the backup cannot be decrypted on this device — restore it on the original device.
  3. Check CryptoUtils.getMode availability and pick a supported mode for new backups to keep them portable.

Example fix

// before
BackupMetadataV5 meta = MetadataManager.readMetadata(backupItem);
// after
String mode = MetadataManager.getInfo(backupItem).crypto;
if (!CryptoUtils.isAvailable(mode)) {
    throw new IOException("Crypto mode " + mode + " is unavailable on this device");
}
BackupMetadataV5 meta = MetadataManager.readMetadata(backupItem);
Defensive patterns

Strategy: validation

Validate before calling

String mode = backupInfo.crypto;
if (!CryptoUtils.isAvailable(mode)) {
    throw new IOException("Crypto mode " + mode + " unavailable; configure keys or use the original device");
}

Try / catch

try {
    BackupMetadataV5 meta = MetadataManager.readMetadata(backupItem);
} catch (IOException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Mode ")) {
        // prompt user to provide decryption credentials or restore on the original device
    } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12). Data as JSON: /api/errors/d789591df30725e7. Report an issue: GitHub.