asLody/VirtualApp · error · java.lang.IllegalStateException

Too many active sessions for UID

Error message

Too many active sessions for UID 

What it means

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.

Solutions

  1. Call session.abandon() on sessions you will not commit (especially in catch/finally blocks).
  2. Serialize installs: commit or abandon the current session before creating the next.
  3. Track and clean up leaked sessions from previous runs (e.g. via PackageInstaller.getAllSessions / mySessions and abandon stale ones).

Example fix

// before
for (File apk : apks) {
    int id = installer.createSession(params);
    writeApk(installer.openSession(id), apk); // may fail -> session leaked
}

// after
for (File apk : apks) {
    Session session = null;
    try {
        session = installer.openSession(installer.createSession(params));
        writeApk(session, apk);
        session.commit(callback);
        session = null;
    } finally {
        if (session != null) session.abandon();
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Best effort pre-check of your own active session count before creating more
List<SessionInfo> mine = installer.getMySessions();
long active = mine.stream().filter(s -> s.isActive()).count();
// if active >= MAX_ACTIVE_SESSIONS, abandon stale sessions first

Try / catch

try {
    sessionId = installer.createSession(params);
} catch (IllegalStateException e) {
    if (String.valueOf(e.getMessage()).startsWith("Too many active sessions")) {
        abandonStaleSessions();
        sessionId = installer.createSession(params);
    } else throw e;
}

Prevention

When it happens

Trigger: Calling createSession repeatedly without commit()ing or abandon()ing previous sessions until activeCount >= MAX_ACTIVE_SESSIONS for the app's UID.

Common situations: 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.

Related errors


AI-assisted analysis of asLody/VirtualApp@666fefcb5d (2026-09-09). Data as JSON: /api/errors/ef74432bc2283eb5. Report an issue: GitHub.

Appendix: source

Thrown at VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/installer/VPackageInstallerService.java:114

    @Override
    public int createSession(SessionParams params, String installerPackageName, int userId) throws RemoteException {
        try {
            return createSessionInternal(params, installerPackageName, userId);
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }
    }

    private int createSessionInternal(SessionParams params, String installerPackageName, int userId)
            throws IOException {
        final int callingUid = VBinder.getCallingUid();
        final int sessionId;
        final PackageInstallerSession session;
        synchronized (mSessions) {
            // Sanity check that installer isn't going crazy
            final int activeCount = getSessionCount(mSessions, callingUid);
            if (activeCount >= MAX_ACTIVE_SESSIONS) {
                throw new IllegalStateException(
                        "Too many active sessions for UID " + callingUid);
            }
            sessionId = allocateSessionIdLocked();
            session = new PackageInstallerSession(mInternalCallback, mContext, mInstallHandler.getLooper(), installerPackageName, sessionId, userId, callingUid, params, VEnvironment.getPackageInstallerStageDir());
        }
        mCallbacks.notifySessionCreated(session.sessionId, session.userId);
        return sessionId;
    }

    @Override
    public void updateSessionAppIcon(int sessionId, Bitmap appIcon) {
        synchronized (mSessions) {
            final PackageInstallerSession session = mSessions.get(sessionId);
            if (session == null || !isCallingUidOwner(session)) {
                throw new SecurityException("Caller has no access to session " + sessionId);
            }

            session.params.appIcon = appIcon;

View on GitHub (pinned to 666fefcb5d)