{"record":{"id":"f409a665f497d2d5","repo":"MuntashirAkon/AppManager","slug":"package-cannot-be-parsed","errorCode":null,"errorMessage":"Package cannot be parsed.","messagePattern":"Package cannot be parsed\\.","errorType":"exception","errorClass":"PackageManager.NameNotFoundException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/apk/installer/PackageInstallerViewModel.java","lineNumber":366,"sourceCode":"        mSelectedSplits.clear();\n        mPackageParseResultLiveData.setValue(null);\n    }\n\n    @WorkerThread\n    @NonNull\n    private PackageInfo loadNewPackageInfo(@NonNull ApkFile apkFile) throws PackageManager.NameNotFoundException, IOException {\n        String apkPath = apkFile.getBaseEntry().getFile(false).getAbsolutePath();\n        int flags = PackageManager.GET_PERMISSIONS\n                | PackageManager.GET_ACTIVITIES | PackageManager.GET_RECEIVERS | PackageManager.GET_PROVIDERS\n                | PackageManager.GET_SERVICES | MATCH_DISABLED_COMPONENTS | GET_SIGNING_CERTIFICATES_APK\n                | PackageManager.GET_CONFIGURATIONS | PackageManager.GET_SHARED_LIBRARY_FILES;\n        PackageInfo packageInfo = mPm.getPackageArchiveInfo(apkPath, flags);\n        if (packageInfo == null) {\n            // Previous method could return null if the APK isn't signed. So, try without it.\n            packageInfo = mPm.getPackageArchiveInfo(apkPath, flags & ~GET_SIGNING_CERTIFICATES_APK);\n        }\n        if (packageInfo == null) {\n            throw new PackageManager.NameNotFoundException(\"Package cannot be parsed.\");\n        }\n        packageInfo.applicationInfo.sourceDir = apkPath;\n        packageInfo.applicationInfo.publicSourceDir = apkPath;\n        return packageInfo;\n    }\n\n    public static final class PackageParseResult {\n        @NonNull\n        private final String operationId;\n        @NonNull\n        private final PackageInfo newPackageInfo;\n        @Nullable\n        private final PackageInfo installedPackageInfo;\n        @NonNull\n        private final ApkSource apkSource;\n        @NonNull\n        private final ApkFile apkFile;\n        @NonNull","sourceCodeStart":348,"sourceCodeEnd":384,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/apk/installer/PackageInstallerViewModel.java#L348-L384","documentation":"PackageInstallerViewModel.loadNewPackageInfo throws PackageManager.NameNotFoundException(\"Package cannot be parsed.\") when PackageManager.getPackageArchiveInfo() returns null for the given APK path, both with and without the GET_SIGNING_CERTIFICATES flag. It means the framework's PackageParser could not extract a PackageInfo from the file, so the APK is not a readable/valid Android package. The installer cannot proceed without package metadata.","triggerScenarios":"Calling the installer flow (newPackageInfo -> loadNewPackageInfo) with an apkPath whose file is not a parseable APK: corrupted/partial download, non-APK file with .apk extension, path on inaccessible storage, or a malformed resource/manifest table the platform parser rejects.","commonSituations":"Sideloading an interrupted download, testing a placeholder/renamed file, split APKs assembled incorrectly, APKs built with features the current OS version cannot parse, or files under app-private storage not yet readable by the parsing process.","solutions":["Verify the file exists and is a complete APK: check File length > 0 and that the first bytes are the ZIP magic 'PK'.","Re-download or re-obtain the APK; compare its checksum against the source to rule out corruption.","Test parsing outside the app with aapt dump badging <apk> to see what the parser dislikes.","If using split/merged APKs, rebuild the merge so the base APK contains a valid binary AndroidManifest.xml.","Check storage permissions / Storage Access Framework URI resolution so the path is actually readable before calling getPackageArchiveInfo."],"exampleFix":"// before\nPackageInfo pi = mPm.getPackageArchiveInfo(apkPath, flags);\nif (pi == null) throw new PackageManager.NameNotFoundException(\"Package cannot be parsed.\");\n// after\nFile apkFile = new File(apkPath);\nif (!apkFile.isFile() || apkFile.length() < 4) {\n    throw new IOException(\"APK missing or truncated: \" + apkPath);\n}\nPackageInfo pi = mPm.getPackageArchiveInfo(apkPath, flags);\nif (pi == null) {\n    throw new PackageManager.NameNotFoundException(\"Package cannot be parsed: \" + apkPath);\n}","handlingStrategy":"try-catch","validationCode":"File f = new File(apkPath);\nif (!f.isFile() || f.length() < 4) return false;\ntry (RandomAccessFile raf = new RandomAccessFile(f, \"r\")) {\n    return raf.read() == 'P' && raf.read() == 'K';\n}","typeGuard":"static boolean isPlausibleApk(String apkPath) {\n    File f = new File(apkPath);\n    return f.isFile() && f.length() >= 22; // minimal ZIP header + EOCD\n}","tryCatchPattern":"try {\n    PackageInfo pi = viewModel.newPackageInfo(apkPath);\n} catch (PackageManager.NameNotFoundException e) {\n    Toast.makeText(ctx, \"APK is corrupt or not an Android package\", Toast.LENGTH_LONG).show();\n    Log.e(TAG, \"getPackageArchiveInfo returned null for \" + apkPath, e);\n}","preventionTips":["Verify file size and ZIP magic before handing the path to the installer.","Re-download APKs over resumable/verified transfers and compare checksums.","Never rename arbitrary files to .apk and feed them to the installer.","Log the APK path and size whenever parsing fails to speed up diagnosis."],"tags":["android","apk","package-manager","installer","parse-failure"],"backgroundTag":"schema-validation-failed","analyzedSha":"0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5","analyzedAt":"2026-09-12T14:03:37.243Z","contentChangedAt":"2026-09-12T14:03:37.243Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}