{"record":{"id":"b3a09a807d9d2261","repo":"MuntashirAkon/AppManager","slug":"could-not-fetch-package-info","errorCode":null,"errorMessage":"Could not fetch package info","messagePattern":"Could not fetch package info","errorType":"exception","errorClass":"BackupException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/backup/convert/SBConverter.java","lineNumber":285,"sourceCode":"    }\n\n    @SuppressLint(\"WrongConstant\")\n    @NonNull\n    private BackupMetadataV2 generateMetadata() throws BackupException {\n        BackupMetadataV2 metadataV2 = new BackupMetadataV2();\n        mCachedApk = FileUtils.getTempPath(mPackageName, \"base.apk\");\n        try (InputStream pis = getApkFile().openInputStream()) {\n            try (OutputStream fos = mCachedApk.openOutputStream()) {\n                IoUtils.copy(pis, fos);\n            }\n            mFilesToBeDeleted.add(getApkFile());\n        } catch (IOException e) {\n            throw new BackupException(\"Could not cache APK file\", e);\n        }\n        String filePath = Objects.requireNonNull(mCachedApk.getFilePath());\n        PackageInfo packageInfo = mPm.getPackageArchiveInfo(filePath, 0);\n        if (packageInfo == null) {\n            throw new BackupException(\"Could not fetch package info\");\n        }\n        mPackageInfo = packageInfo;\n        Objects.requireNonNull(mPackageInfo.applicationInfo);\n        mPackageInfo.applicationInfo.publicSourceDir = filePath;\n        mPackageInfo.applicationInfo.sourceDir = filePath;\n        ApplicationInfo applicationInfo = mPackageInfo.applicationInfo;\n\n        if (!mPackageInfo.packageName.equals(mPackageName)) {\n            throw new BackupException(\"Package name mismatch: Expected=\" + mPackageName + \", Actual=\" + mPackageInfo.packageName);\n        }\n\n        metadataV2.label = applicationInfo.loadLabel(mPm).toString();\n        metadataV2.packageName = mPackageName;\n        metadataV2.versionName = mPackageInfo.versionName;\n        metadataV2.versionCode = PackageInfoCompat.getLongVersionCode(mPackageInfo);\n        metadataV2.isSystem = false;\n        metadataV2.hasRules = false;\n        metadataV2.backupTime = mBackupTime;","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/backup/convert/SBConverter.java#L267-L303","documentation":"Thrown by SBConverter.generateMetadata when PackageManager.getPackageArchiveInfo returns null for the cached APK. This means the APK file could not be parsed as a valid Android package (invalid zip, corrupt manifest, wrong architecture-independent header), so label/version/package name cannot be derived.","triggerScenarios":"The cached base.apk is truncated or corrupt; the file is not actually an APK (e.g., wrong file stored under apkName); getPackageArchiveInfo fails to read the compiled manifest on this Android version.","commonSituations":"Partially downloaded or interrupted Swift Backup exports; source archives created by modified/custom backup tools storing non-APK payloads; heavily obfuscated or broken APKs on newer Android parsing rules.","solutions":["Verify the cached APK opens as a valid zip and contains AndroidManifest.xml (try aapt dump badging).","Re-export or re-copy the source backup to get a complete APK.","Ensure metadata.apkName points at the real base APK, not a split or unrelated file.","Test the same APK installs via a package installer; if it doesn't, the APK itself is corrupt."],"exampleFix":"// before: assume parse succeeds\nPackageInfo pi = pm.getPackageArchiveInfo(path, 0);\n// after: validate archive before asking PM\ntry (ZipFile zf = new ZipFile(path)) {\n    if (zf.getEntry(\"AndroidManifest.xml\") == null)\n        throw new IOException(\"not a valid APK: \" + path);\n}\nPackageInfo pi = pm.getPackageArchiveInfo(path, 0);\nif (pi == null) throw new IOException(\"PM could not parse APK: \" + path);","handlingStrategy":"validation","validationCode":"PackageInfo pi = pm.getPackageArchiveInfo(cachedApkPath, 0);\nif (pi == null) {\n    // APK not parseable; fail before conversion instead of mid-way\n    try (ZipFile zf = new ZipFile(cachedApkPath)) {\n        if (zf.getEntry(\"AndroidManifest.xml\") == null)\n            throw new IOException(\"not a valid APK\");\n    }\n}","typeGuard":null,"tryCatchPattern":"try { converter.convert(); }\ncatch (BackupException e) {\n    if (e.getMessage().equals(\"Could not fetch package info\")) {\n        // treat source APK as corrupt; re-export or reject the source\n    }\n}","preventionTips":["Verify APKs with 'aapt dump badging' before conversion","Reject truncated source archives up front","Ensure apkName points to a real base APK, not a split or asset","Test suspicious APKs with an installer before relying on them"],"tags":["android","backup","apk","package-manager"],"backgroundTag":"unexpected-response-shape","analyzedSha":"0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5","analyzedAt":"2026-09-12T14:03:37.243Z","contentChangedAt":"2026-09-12T14:03:37.243Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}