{"record":{"id":"03513d2254660483","repo":"asLody/VirtualApp","slug":"install-failed-invalid-apk","errorCode":"INSTALL_FAILED_INVALID_APK","errorMessage":"No packages staged","messagePattern":"No packages staged","errorType":"error_code","errorClass":"PackageManagerException","httpStatus":null,"severity":"error","filePath":"VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/installer/PackageInstallerSession.java","lineNumber":189,"sourceCode":"            public void onUserActionRequired(Intent intent) {\n                throw new IllegalStateException();\n            }\n\n            @Override\n            public void onPackageInstalled(String basePackageName, int returnCode, String msg,\n                                           Bundle extras) {\n                destroyInternal();\n                dispatchSessionFinished(returnCode, msg, extras);\n            }\n        };\n    }\n\n    private void validateInstallLocked() throws PackageManagerException {\n        mResolvedBaseFile = null;\n        mResolvedStagedFiles.clear();\n        File[] addedFiles = this.mResolvedStageDir.listFiles();\n        if (addedFiles == null || addedFiles.length == 0) {\n            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, \"No packages staged\");\n        }\n        for (File addedFile : addedFiles) {\n            if (!addedFile.isDirectory()) {\n                final String targetName = \"base.apk\";\n                final File targetFile = new File(mResolvedStageDir, targetName);\n                if (!addedFile.equals(targetFile)) {\n                    addedFile.renameTo(targetFile);\n                }\n                mResolvedBaseFile = targetFile;\n                mResolvedStagedFiles.add(targetFile);\n            }\n        }\n        if (mResolvedBaseFile == null) {\n            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,\n                    \"Full install must include a base package\");\n        }\n    }\n","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/asLody/VirtualApp/blob/666fefcb5d3f39cc944001c3457c38ffd6544c87/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/installer/PackageInstallerSession.java#L171-L207","documentation":"validateInstallLocked lists the resolved stage directory and throws PackageManagerException(INSTALL_FAILED_INVALID_APK, \"No packages staged\") when the directory is empty or unlistable. An install session must contain at least one staged APK file before it can be validated and installed.","triggerScenarios":"Calling commit() on a session where no APK was ever written into the stage dir; writeStream failed silently; the stage dir path resolves to a nonexistent/non-listable directory (listFiles() == null).","commonSituations":"Forgetting to stream the APK before commit; passing an empty/closed InputStream so zero bytes were written; disk-full or IO error during streaming that left the stage dir empty; wrong stage dir due to resolveStageDir issues.","solutions":["Write the APK into the session via openWrite/writeStream (and commit the stream) before calling commit().","Check the return of stream commit and verify the staged file exists and is non-empty before sealing.","Catch IOException during streaming and abort/recreate the session instead of proceeding to commit.","Verify sufficient storage space and readable stage directory."],"exampleFix":"// before\nPackageInstallerSession session = ...;\nsession.commit(statusReceiver); // nothing staged\n// after\ntry (OutputStream out = session.openWrite(\"base\", 0, apk.length())) {\n    out.write(bytes);\n    session.commitStream(out);\n}\nsession.seal();\nsession.commit(statusReceiver);","handlingStrategy":"validation","validationCode":"File stageDir = session.getStageDir();\nFile[] files = stageDir != null ? stageDir.listFiles() : null;\nif (files == null || files.length == 0) {\n    throw new IllegalStateException(\"No APK staged; write the APK before commit\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    session.commit(statusReceiver);\n} catch (PackageManagerException e) {\n    if (e.error == INSTALL_FAILED_INVALID_APK) {\n        Log.e(TAG, \"Nothing staged: \" + e.getMessage());\n        restartInstallFlow(apkFile);\n    }\n}","preventionTips":["Always stream and commit the APK before seal/commit.","Verify staged file size matches the source APK size.","Handle IOException during streaming by aborting the session, not continuing.","Check free disk space before starting an install."],"tags":["android","package-install","apk","validation"],"backgroundTag":"empty-required-field","analyzedSha":"666fefcb5d3f39cc944001c3457c38ffd6544c87","analyzedAt":"2026-09-09T11:09:01.694Z","contentChangedAt":"2026-09-09T11:09:01.694Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}