{"record":{"id":"fdd7901610c3aa21","repo":"MuntashirAkon/AppManager","slug":"invalid-queue-item","errorCode":null,"errorMessage":"Invalid queue item.","messagePattern":"Invalid queue item\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/apk/installer/PackageInstallerViewModel.java","lineNumber":285,"sourceCode":"\n    @WorkerThread\n    @NonNull\n    private PackageParseResult loadPackageInfo(@NonNull ApkQueueItem apkQueueItem) throws Throwable {\n        ApkSource apkSource;\n        ApkFile apkFile = null;\n        try {\n            PackageInfo installedPackageInfo = null;\n            if (apkQueueItem.isInstallExisting()) {\n                String packageName = apkQueueItem.getPackageName();\n                if (packageName == null) {\n                    throw new IllegalArgumentException(\"Package name not set for install-existing.\");\n                }\n                installedPackageInfo = loadInstalledPackageInfo(packageName);\n                apkSource = ApkSource.getApkSource(installedPackageInfo.applicationInfo);\n            } else {\n                apkSource = apkQueueItem.getApkSource();\n                if (apkSource == null) {\n                    throw new IllegalArgumentException(\"Invalid queue item.\");\n                }\n            }\n            apkFile = apkSource.resolve();\n            PackageInfo newPackageInfo = loadNewPackageInfo(apkFile);\n            String packageName = newPackageInfo.packageName;\n            throwIfInterrupted();\n            if (installedPackageInfo == null) {\n                try {\n                    installedPackageInfo = loadInstalledPackageInfo(packageName);\n                } catch (PackageManager.NameNotFoundException ignore) {\n                }\n            }\n            throwIfInterrupted();\n            String appLabel = mPm.getApplicationLabel(newPackageInfo.applicationInfo).toString();\n            Drawable appIcon = mPm.getApplicationIcon(newPackageInfo.applicationInfo);\n            int trackerCount = ComponentUtils.getTrackerComponentsCountForPackage(newPackageInfo);\n            throwIfInterrupted();\n            boolean isSignatureDifferent = installedPackageInfo != null","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/apk/installer/PackageInstallerViewModel.java#L267-L303","documentation":"PackageInstallerViewModel.loadPackageInfo() obtains the ApkSource from a non-install-existing queue item via apkQueueItem.getApkSource(); if it returns null the queue item carries no installable source and an IllegalArgumentException ('Invalid queue item.') is thrown.","triggerScenarios":"Passing an ApkQueueItem that is neither install-existing nor holds an APK source — e.g. a default-constructed/empty queue item, one whose source was revoked or failed to deserialize from JSON, or a null source returned by a dead content-URI.","commonSituations":"Restoring an install session from JSON where apk_source was dropped (e.g. persisted URI permission expired); constructing a queue item and forgetting to attach the APK file/URI; race conditions where the source file was deleted before the ViewModel loaded it.","solutions":["Attach a valid ApkSource (APK file/content URI) to the queue item before handing it to the ViewModel","Verify persisted content-URI permissions (takePersistableUriPermission) so the source survives process restarts","Check the APK file still exists at the referenced path/URI and re-prompt the user if it was deleted","Catch IllegalArgumentException and treat it as 'queue item unusable', restarting the install flow from file selection"],"exampleFix":"// before\nApkQueueItem item = ApkQueueItem.fromJson(json); // apk_source lost\nvm.loadPackageInfo(item); // throws Invalid queue item.\n// after\nApkQueueItem item = ApkQueueItem.fromJson(json);\nif (!item.isInstallExisting() && item.getApkSource() == null) {\n    item.setApkSource(new ApkSource(pickApkUri()));\n}\nvm.loadPackageInfo(item);","handlingStrategy":"try-catch","validationCode":"if (!item.isInstallExisting() && item.getApkSource() == null) {\n    throw new IllegalStateException(\"Queue item carries no APK source; re-pick the APK.\");\n}","typeGuard":"boolean isUsableQueueItem(ApkQueueItem item) {\n    return item.isInstallExisting()\n        ? item.getPackageName() != null\n        : item.getApkSource() != null;\n}","tryCatchPattern":"try {\n    vm.loadPackageInfo(item);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"Invalid queue item\")) {\n        restartInstallFromPicker();\n    }\n}","preventionTips":["Take persistable URI permissions so APK sources survive process restarts","Check the APK file/URI still resolves before enqueueing","Never pass default-constructed queue items to the installer ViewModel"],"tags":["android","apk-installer","null-argument","queue"],"backgroundTag":"null-argument","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"}