{"record":{"id":"bc65c918994f4599","repo":"MuntashirAkon/AppManager","slug":"app-not-installed-it-only-has-data","errorCode":null,"errorMessage":"App not installed. It only has data.","messagePattern":"App not installed\\. It only has data\\.","errorType":"exception","errorClass":"ApkFile.ApkFileException","httpStatus":null,"severity":"warning","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/details/AppDetailsViewModel.java","lineNumber":1118,"sourceCode":"    private void setPackageInfo(boolean reload) {\n        // Package name cannot be null\n        if (mPackageName == null) return;\n        // Wait for component blocker to appear\n        synchronized (mBlockerLocker) {\n            waitForBlockerOrExit();\n        }\n        if (!reload && mPackageInfo != null) return;\n        try {\n            try {\n                mInstalledPackageInfo = PackageManagerCompat.getPackageInfo(mPackageName, PackageManager.GET_META_DATA\n                                | PackageManager.GET_PERMISSIONS | PackageManager.GET_ACTIVITIES | MATCH_DISABLED_COMPONENTS\n                                | PackageManager.GET_RECEIVERS | PackageManager.GET_PROVIDERS | MATCH_UNINSTALLED_PACKAGES\n                                | PackageManager.GET_SERVICES | PackageManager.GET_CONFIGURATIONS | GET_SIGNING_CERTIFICATES\n                                | PackageManager.GET_SHARED_LIBRARY_FILES | PackageManager.GET_URI_PERMISSION_PATTERNS\n                                | PackageManagerCompat.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES,\n                        mUserId);\n                if (!ApplicationInfoCompat.isInstalled(mInstalledPackageInfo.applicationInfo)) {\n                    throw new ApkFile.ApkFileException(\"App not installed. It only has data.\");\n                }\n            } catch (Throwable e) {\n                Log.e(TAG, e);\n                mInstalledPackageInfo = null;\n            }\n            if (mExternalApk) {\n                // Do not get signatures via Android framework as it will simply return NULL without any clarifications.\n                // All signatures are fetched using PackageUtils where a fallback method is used in case the PackageInfo\n                // didn't load any signature. So, we should be safe from any harm.\n                mPackageInfo = mPackageManager.getPackageArchiveInfo(mApkPath, PackageManager.GET_PERMISSIONS\n                        | PackageManager.GET_ACTIVITIES | PackageManager.GET_RECEIVERS | PackageManager.GET_PROVIDERS\n                        | PackageManager.GET_SERVICES | MATCH_DISABLED_COMPONENTS | PackageManager.GET_CONFIGURATIONS\n                        | PackageManager.GET_SHARED_LIBRARY_FILES | PackageManager.GET_URI_PERMISSION_PATTERNS\n                        | PackageManager.GET_META_DATA);\n                if (mPackageInfo == null) {\n                    throw new PackageManager.NameNotFoundException(\"Package cannot be parsed\");\n                }\n                if (mInstalledPackageInfo == null) {","sourceCodeStart":1100,"sourceCodeEnd":1136,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/details/AppDetailsViewModel.java#L1100-L1136","documentation":"When loading details, the ViewModel fetches PackageInfo with MATCH_UNINSTALLED_PACKAGES so data-only remnants of uninstalled apps can still be seen. But if ApplicationInfoCompat.isInstalled() reports false, the entry is only leftover data (no APK) and detail views that require a real app cannot proceed, so ApkFileException('App not installed. It only has data.') is thrown. The outer catch resets mInstalledPackageInfo to null so the ViewModel falls back to external-APK mode.","triggerScenarios":"Opening App Details for a package that was uninstalled without deleting its data (or whose data remains) on the queried userId; the package resolves via MATCH_UNINSTALLED_PACKAGES but ApplicationInfo flags indicate it is not installed (e.g. only instant/archived/data remnants).","commonSituations":"User browses 'data-only' apps in App Manager and taps one expecting app info; a backup restore left data behind after uninstall; hidden/suspended apps misdetected as uninstalled.","solutions":["Reinstall the app; the data will be re-attached and details will load","If you only want data operations (backup/clear), use a code path that tolerates data-only packages instead of the APK-detail path","Filter data-only packages out of any list feed that launches AppDetailsViewModel","Check ApplicationInfoCompat.isInstalled() before constructing the ViewModel"],"exampleFix":"// before\nviewModel.setPackage(dataOnlyPackageName); // ApkFileException\n// after\nPackageInfo pi = pm.getPackageInfo(pkg, MATCH_UNINSTALLED_PACKAGES | ...);\nif (pi != null && ApplicationInfoCompat.isInstalled(pi.applicationInfo)) {\n    viewModel.setPackage(pkg);\n} else {\n    showDataOnlyAppNotice();\n}","handlingStrategy":"validation","validationCode":"PackageInfo pi = pm.getPackageInfo(pkg, PackageManager.MATCH_UNINSTALLED_PACKAGES);\nboolean usableForDetails = pi != null && ApplicationInfoCompat.isInstalled(pi.applicationInfo);","typeGuard":"boolean isDataOnly(PackageInfo pi) {\n    return pi != null && !ApplicationInfoCompat.isInstalled(pi.applicationInfo);\n}","tryCatchPattern":"try {\n    viewModel.setPackage(pkg);\n} catch (ApkFile.ApkFileException e) {\n    showDataOnlyAppScreen(); // offer reinstall / data operations only\n}","preventionTips":["Mark data-only entries in lists and route them to a data-only UI","Prompt users to reinstall data-only apps instead of opening full details","Check ApplicationInfoCompat.isInstalled before navigation"],"tags":["android","package-manager","data-only","not-installed"],"backgroundTag":"entity-not-found","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"}