{"record":{"id":"b261c55d600053b4","repo":"beemdevelopment/Aegis","slug":"export-list-contains-entries-from-different-batche","errorCode":null,"errorMessage":"Export list contains entries from different batches","messagePattern":"Export list contains entries from different batches","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/src/main/java/com/beemdevelopment/aegis/otp/GoogleAuthInfo.java","lineNumber":362,"sourceCode":"        public List<GoogleAuthInfo> getEntries() {\n            return _entries;\n        }\n\n        public int getBatchSize() {\n            return _batchSize;\n        }\n\n        public int getBatchIndex() {\n            return _batchIndex;\n        }\n\n        public int getBatchId() {\n            return _batchId;\n        }\n\n        public static List<Integer> getMissingIndices(@NonNull List<Export> exports) throws IllegalArgumentException {\n            if (!isSingleBatch(exports)) {\n                throw new IllegalArgumentException(\"Export list contains entries from different batches\");\n            }\n\n            List<Integer> indicesMissing = new ArrayList<>();\n            if (exports.isEmpty()) {\n                return indicesMissing;\n            }\n\n            Set<Integer> indicesPresent = exports.stream()\n                    .map(Export::getBatchIndex)\n                    .collect(Collectors.toSet());\n\n            for (int i = 0; i < exports.get(0).getBatchSize(); i++) {\n                if (!indicesPresent.contains(i)) {\n                    indicesMissing.add(i);\n                }\n            }\n\n            return indicesMissing;","sourceCodeStart":344,"sourceCodeEnd":380,"githubUrl":"https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/app/src/main/java/com/beemdevelopment/aegis/otp/GoogleAuthInfo.java#L344-L380","documentation":"Google Authenticator exports are batched; each Export carries a batchId and index. getMissingIndices requires all supplied exports to belong to one batch so missing indices can be computed; mixing entries from different transfers is ambiguous and raises IllegalArgumentException.","triggerScenarios":"Calling GoogleAuthInfo.Export.getMissingIndices with a list of Export objects whose getBatchId() values are not all identical (isSingleBatch returns false).","commonSituations":"Collecting partial exports across multiple separate transfer sessions and combining them, restoring exports from different devices, or a UI bug that mixes pending transfer batches.","solutions":["Pass only Export objects from a single transfer/batch; group them by getBatchId() first","Restart the export/transfer to collect a complete single batch","Split the list by batchId and call getMissingIndices per group"],"exampleFix":"// before\nGoogleAuthInfo.Export.getMissingIndices(exportAandB); // mixed batches\n// after\nMap<Integer, List<Export>> byBatch = exports.stream().collect(groupingBy(Export::getBatchId));\nbyBatch.values().forEach(GoogleAuthInfo.Export::getMissingIndices);","handlingStrategy":"validation","validationCode":"Set<Integer> batches = exports.stream().map(GoogleAuthInfo.Export::getBatchId).collect(toSet());\nif (batches.size() > 1) throw new IllegalArgumentException(\"Mixed export batches\");","typeGuard":null,"tryCatchPattern":"try {\n    List<Integer> missing = GoogleAuthInfo.Export.getMissingIndices(exports);\n} catch (IllegalArgumentException e) {\n    // group exports by batchId and process each batch separately\n}","preventionTips":["Track exports per transfer session and never mix sessions","Group by getBatchId() before computing missing indices","Complete one transfer before starting another"],"tags":["otp","batch","export"],"backgroundTag":"invalid-argument-value","analyzedSha":"d6f4e5925a97e4e91593f1542085eae03432a759","analyzedAt":"2026-09-08T00:46:31.111Z","contentChangedAt":"2026-09-08T00:46:31.111Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}