MuntashirAkon/AppManager · error · IOException

The number of input and output files are not the same.

Error message

The number of input and output files are not the same.

What it means

AESCrypto.handleFiles processes input and output files in index pairs. If the caller passes arrays of different lengths, no 1:1 input→output mapping exists, so an IOException is thrown before any cipher work starts.

Solutions

  1. Build input and output Path arrays in the same loop so lengths always match
  2. Assert lengths are equal before calling encrypt/decrypt and fail fast with your own message
  3. Compute output paths from each input path (e.g. input + ".enc") instead of a hand-built list

Example fix

// before
Path[] out = {p1, p2};
crypto.encrypt(new Path[]{p1, p2, p3}, out);
// after
Path[] out = new Path[]{p1, p2, p3};
crypto.encrypt(new Path[]{p1, p2, p3}, out);
Defensive patterns

Strategy: validation

Validate before calling

if (inFiles.length != outFiles.length || inFiles.length == 0) {
    throw new IllegalArgumentException("input/output length mismatch: " + inFiles.length + " vs " + outFiles.length);
}

Try / catch

try { crypto.encrypt(in, out); } catch (IOException e) {
    if (e.getMessage().contains("not the same")) {
        // fix caller-side array construction
    }
}

Prevention

When it happens

Trigger: Calling encrypt(Path[] in, Path[] out) or decrypt(...) with inputFiles.length != outputFiles.length (and inputFiles non-empty).

Common situations: Mismatches from building the two arrays in different loops, skipping files whose encryption failed earlier, or passing a single output path array for many inputs.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at app/src/main/java/io/github/muntashirakon/AppManager/crypto/AESCrypto.java:168

            throws IOException {
        // Init cipher
        GCMModeCipher cipher = GCMBlockCipher.newInstance(AESEngine.newInstance());
        cipher.init(false, getParams());
        // Convert encrypted stream to unencrypted stream
        try (InputStream cipherIS = new CipherInputStream(encryptedStream, cipher)) {
            IoUtils.copy(cipherIS, unencryptedStream);
        }
    }

    @WorkerThread
    private void handleFiles(boolean forEncryption, @NonNull Path[] inputFiles, @NonNull Path[] outputFiles) throws IOException {
        // `files` is never null here
        if (inputFiles.length == 0) {
            Log.d(TAG, "No files to de/encrypt");
            return;
        }
        if (inputFiles.length != outputFiles.length) {
            throw new IOException("The number of input and output files are not the same.");
        }
        // Init cipher
        GCMModeCipher cipher = GCMBlockCipher.newInstance(AESEngine.newInstance());
        cipher.init(forEncryption, getParams());
        // Encrypt/decrypt files
        for (int i = 0; i < inputFiles.length; i++) {
            Path inputPath = inputFiles[i];
            Path outputPath = outputFiles[i];
            Log.i(TAG, "Input: %s\nOutput: %s", inputPath, outputPath);
            try (InputStream is = inputPath.openInputStream();
                 OutputStream os = outputPath.openOutputStream()) {
                if (forEncryption) {
                    try (OutputStream cipherOS = new CipherOutputStream(os, cipher)) {
                        IoUtils.copy(is, cipherOS);
                    }
                } else {  // Cipher.DECRYPT_MODE
                    try (InputStream cipherIS = new CipherInputStream(is, cipher)) {
                        IoUtils.copy(cipherIS, os);

View on GitHub (pinned to 0152f468fc)