{"record":{"id":"8cbeca747d77fe5b","repo":"MuntashirAkon/AppManager","slug":"the-number-of-input-and-output-files-are-not-the-same","errorCode":null,"errorMessage":"The number of input and output files are not the same.","messagePattern":"The number of input and output files are not the same\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/crypto/AESCrypto.java","lineNumber":168,"sourceCode":"            throws IOException {\n        // Init cipher\n        GCMModeCipher cipher = GCMBlockCipher.newInstance(AESEngine.newInstance());\n        cipher.init(false, getParams());\n        // Convert encrypted stream to unencrypted stream\n        try (InputStream cipherIS = new CipherInputStream(encryptedStream, cipher)) {\n            IoUtils.copy(cipherIS, unencryptedStream);\n        }\n    }\n\n    @WorkerThread\n    private void handleFiles(boolean forEncryption, @NonNull Path[] inputFiles, @NonNull Path[] outputFiles) throws IOException {\n        // `files` is never null here\n        if (inputFiles.length == 0) {\n            Log.d(TAG, \"No files to de/encrypt\");\n            return;\n        }\n        if (inputFiles.length != outputFiles.length) {\n            throw new IOException(\"The number of input and output files are not the same.\");\n        }\n        // Init cipher\n        GCMModeCipher cipher = GCMBlockCipher.newInstance(AESEngine.newInstance());\n        cipher.init(forEncryption, getParams());\n        // Encrypt/decrypt files\n        for (int i = 0; i < inputFiles.length; i++) {\n            Path inputPath = inputFiles[i];\n            Path outputPath = outputFiles[i];\n            Log.i(TAG, \"Input: %s\\nOutput: %s\", inputPath, outputPath);\n            try (InputStream is = inputPath.openInputStream();\n                 OutputStream os = outputPath.openOutputStream()) {\n                if (forEncryption) {\n                    try (OutputStream cipherOS = new CipherOutputStream(os, cipher)) {\n                        IoUtils.copy(is, cipherOS);\n                    }\n                } else {  // Cipher.DECRYPT_MODE\n                    try (InputStream cipherIS = new CipherInputStream(is, cipher)) {\n                        IoUtils.copy(cipherIS, os);","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/crypto/AESCrypto.java#L150-L186","documentation":"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.","triggerScenarios":"Calling encrypt(Path[] in, Path[] out) or decrypt(...) with inputFiles.length != outputFiles.length (and inputFiles non-empty).","commonSituations":"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.","solutions":["Build input and output Path arrays in the same loop so lengths always match","Assert lengths are equal before calling encrypt/decrypt and fail fast with your own message","Compute output paths from each input path (e.g. input + \".enc\") instead of a hand-built list"],"exampleFix":"// before\nPath[] out = {p1, p2};\ncrypto.encrypt(new Path[]{p1, p2, p3}, out);\n// after\nPath[] out = new Path[]{p1, p2, p3};\ncrypto.encrypt(new Path[]{p1, p2, p3}, out);","handlingStrategy":"validation","validationCode":"if (inFiles.length != outFiles.length || inFiles.length == 0) {\n    throw new IllegalArgumentException(\"input/output length mismatch: \" + inFiles.length + \" vs \" + outFiles.length);\n}","typeGuard":null,"tryCatchPattern":"try { crypto.encrypt(in, out); } catch (IOException e) {\n    if (e.getMessage().contains(\"not the same\")) {\n        // fix caller-side array construction\n    }\n}","preventionTips":["Build input and output arrays in the same loop","Derive output paths from input paths","Sanity-check array lengths before every encrypt/decrypt call"],"tags":["io","files","crypto","argument-mismatch"],"backgroundTag":"invalid-argument-value","analyzedSha":"0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5","analyzedAt":"2026-09-12T14:03:37.243Z","contentChangedAt":"2026-09-12T14:03:37.243Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}