{"record":{"id":"ef74432bc2283eb5","repo":"asLody/VirtualApp","slug":"too-many-active-sessions-for-uid","errorCode":null,"errorMessage":"Too many active sessions for UID ","messagePattern":"Too many active sessions for UID ","errorType":"exception","errorClass":"java.lang.IllegalStateException","httpStatus":null,"severity":"error","filePath":"VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/installer/VPackageInstallerService.java","lineNumber":114,"sourceCode":"    @Override\n    public int createSession(SessionParams params, String installerPackageName, int userId) throws RemoteException {\n        try {\n            return createSessionInternal(params, installerPackageName, userId);\n        } catch (IOException e) {\n            throw new IllegalStateException(e);\n        }\n    }\n\n    private int createSessionInternal(SessionParams params, String installerPackageName, int userId)\n            throws IOException {\n        final int callingUid = VBinder.getCallingUid();\n        final int sessionId;\n        final PackageInstallerSession session;\n        synchronized (mSessions) {\n            // Sanity check that installer isn't going crazy\n            final int activeCount = getSessionCount(mSessions, callingUid);\n            if (activeCount >= MAX_ACTIVE_SESSIONS) {\n                throw new IllegalStateException(\n                        \"Too many active sessions for UID \" + callingUid);\n            }\n            sessionId = allocateSessionIdLocked();\n            session = new PackageInstallerSession(mInternalCallback, mContext, mInstallHandler.getLooper(), installerPackageName, sessionId, userId, callingUid, params, VEnvironment.getPackageInstallerStageDir());\n        }\n        mCallbacks.notifySessionCreated(session.sessionId, session.userId);\n        return sessionId;\n    }\n\n    @Override\n    public void updateSessionAppIcon(int sessionId, Bitmap appIcon) {\n        synchronized (mSessions) {\n            final PackageInstallerSession session = mSessions.get(sessionId);\n            if (session == null || !isCallingUidOwner(session)) {\n                throw new SecurityException(\"Caller has no access to session \" + sessionId);\n            }\n\n            session.params.appIcon = appIcon;","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/asLody/VirtualApp/blob/666fefcb5d3f39cc944001c3457c38ffd6544c87/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/installer/VPackageInstallerService.java#L96-L132","documentation":"VPackageInstallerService caps concurrently active (non-finalized) install sessions per calling UID at MAX_ACTIVE_SESSIONS. createSessionInternal counts existing sessions for callingUid and, if at the cap, throws IllegalStateException('Too many active sessions for UID ' + callingUid) to stop a runaway installer from exhausting storage/session IDs.","triggerScenarios":"Calling createSession repeatedly without commit()ing or abandon()ing previous sessions until activeCount >= MAX_ACTIVE_SESSIONS for the app's UID.","commonSituations":"Retry loops that create a new session on each failure and never abandon the failed ones; app crash leaving orphaned active sessions that still count; parallel installs of many APKs in one process.","solutions":["Call session.abandon() on sessions you will not commit (especially in catch/finally blocks).","Serialize installs: commit or abandon the current session before creating the next.","Track and clean up leaked sessions from previous runs (e.g. via PackageInstaller.getAllSessions / mySessions and abandon stale ones)."],"exampleFix":"// before\nfor (File apk : apks) {\n    int id = installer.createSession(params);\n    writeApk(installer.openSession(id), apk); // may fail -> session leaked\n}\n\n// after\nfor (File apk : apks) {\n    Session session = null;\n    try {\n        session = installer.openSession(installer.createSession(params));\n        writeApk(session, apk);\n        session.commit(callback);\n        session = null;\n    } finally {\n        if (session != null) session.abandon();\n    }\n}","handlingStrategy":"try-catch","validationCode":"// Best effort pre-check of your own active session count before creating more\nList<SessionInfo> mine = installer.getMySessions();\nlong active = mine.stream().filter(s -> s.isActive()).count();\n// if active >= MAX_ACTIVE_SESSIONS, abandon stale sessions first","typeGuard":null,"tryCatchPattern":"try {\n    sessionId = installer.createSession(params);\n} catch (IllegalStateException e) {\n    if (String.valueOf(e.getMessage()).startsWith(\"Too many active sessions\")) {\n        abandonStaleSessions();\n        sessionId = installer.createSession(params);\n    } else throw e;\n}","preventionTips":["abandon() sessions in finally blocks on failure.","Commit or abandon each session before creating the next.","Clean up orphaned sessions at app startup."],"tags":["illegal-state","session-limit","resource-leak","android"],"backgroundTag":"rate-limit-exceeded","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"}