MuntashirAkon/AppManager · error · BackupException

Incorrect number of APK files:

Error message

Incorrect number of APK files: 

What it means

After decryption, the converter asserts that decryptSourceFiles() returned exactly one APK file (a singleton array), since only one base APK is expected. Any other count means the decryption/normalization step behaved unexpectedly and the subsequent checksum and tar logic would be wrong, so it throws with the actual length. This is an internal invariant check.

Source

Thrown at app/src/main/java/io/github/muntashirakon/AppManager/backup/convert/OABConverter.java:265

    }

    private void backupApkFile() throws BackupException {
        Path[] baseApkFiles;
        try {
            baseApkFiles = new Path[]{mBackupLocation.findFile(CryptoUtils.getAppropriateFilename(
                    mSourceMetadata.apkName, mSourceCryptoMode))};
        } catch (FileNotFoundException e) {
            throw new BackupException("Could not get base.apk file.", e);
        }
        // Decrypt APK file if needed
        try {
            baseApkFiles = ConvertUtils.decryptSourceFiles(baseApkFiles, mSourceCrypto, mSourceCryptoMode, mBackupItem);
        } catch (IOException e) {
            throw new BackupException("Failed to decrypt " + Arrays.toString(baseApkFiles), e);
        }
        // baseApkFiles should be a singleton array
        if (baseApkFiles.length != 1) {
            throw new BackupException("Incorrect number of APK files: " + baseApkFiles.length);
        }
        Path baseApkFile = baseApkFiles[0];
        // Get certificate checksums
        try {
            String[] checksums = ConvertUtils.getChecksumsFromApk(baseApkFile, mDestMetadata.info.checksumAlgo);
            for (int i = 0; i < checksums.length; ++i) {
                mChecksum.add(CERT_PREFIX + i, checksums[i]);
            }
        } catch (Exception ignore) {
        }
        // Backup APK file
        String sourceBackupFilePrefix = BackupUtils.getSourceFilePrefix(getExt(mDestMetadata.info.tarType));
        Path[] sourceFiles;
        try {
            sourceFiles = TarUtils.create(mDestMetadata.info.tarType, baseApkFile, mBackupItem.getUnencryptedBackupPath(), sourceBackupFilePrefix,
                            /* language=regexp */ new String[]{".*\\.apk"}, null, null, false)
                    .toArray(new Path[0]);
        } catch (Throwable th) {

View on GitHub (pinned to 0152f468fc)

Solutions

  1. Ensure the source is a single base APK, not a split-APK bundle; convert one APK at a time.
  2. Clean the backup item's temporary/decrypted output directory of stale files and retry.
  3. Verify the decryptSourceFiles() behavior for your crypto mode matches the expected single-output contract.
  4. Re-create the source backup containing exactly one APK file and rerun the conversion.

Example fix

// before: backup dir holds base.apk + split_config.apk fed through one item
// after: point the converter at a backup containing only base.apk,
// or split the job per APK:
// convert(backupDirWithOnlyBaseApk)
Defensive patterns

Strategy: validation

Validate before calling

// Convert only single-APK sources
if (countApkFilesInBackup(backupDir) != 1) {
    throw new IllegalStateException("Converter expects exactly one base APK in the source backup");
}

Try / catch

try {
    converter.convert(...);
} catch (BackupException e) {
    if (e.getMessage().startsWith("Incorrect number of APK files")) {
        Log.e(TAG, "Decryption returned non-singleton array; clean temp dir and retry", e);
    }
}

Prevention

When it happens

Trigger: In backupApkFile(), baseApkFiles.length != 1 right after ConvertUtils.decryptSourceFiles() at OABConverter.java:265 — e.g. decryption produced 0 or multiple output paths.

Common situations: Source file was a split/multi-APK set so decryption yields several files; the decrypted output directory already contained stale files from a previous run; a decrypt implementation change alters the returned array contents.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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