asLody/VirtualApp · error · SecurityException

not allowed after commit

Error message

 not allowed after commit

What it means

After commit() runs, the session sets mSealed = true; the same assertPreparedAndNotSealed guard then throws SecurityException('<cookie> not allowed after commit') for any subsequent openWrite/openRead/getNames. Sealing freezes the staged payload so the install pass sees a consistent set of APK files.

Solutions

  1. Do not call openWrite/openRead after commit(); create a new session if more data must be staged.
  2. Finish all writes and close all streams before calling commit().
  3. If commit failed, abandon() the session, create a fresh one via createSession, and re-stage everything.

Example fix

// before
session.commit(callback);
OutputStream out = session.openWrite("split2.apk", 0, -1); // SecurityException

// after
try (OutputStream out = session.openWrite("split2.apk", 0, -1)) {
    out.write(splitBytes);
}
session.commit(callback);
Defensive patterns

Strategy: try-catch

Validate before calling

// Track commit state; never call openWrite/openRead after commit()
if (committed) throw new IllegalStateException("Session already committed");

Try / catch

try {
    stream = session.openWrite(name, offset, length);
} catch (SecurityException e) {
    if (String.valueOf(e.getMessage()).endsWith("not allowed after commit")) {
        // create a fresh session and re-stage
    } else throw e;
}

Prevention

When it happens

Trigger: Calling openWrite/openRead/getNames after commit() (or after setPermissionsResult-triggered re-seal); trying to append more data or list files once the session has been submitted for install.

Common situations: Retry logic that re-opens the stream after a failed commit; writing remaining split APKs after commit was already called; keeping a stale session handle around and reusing it post-commit.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

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

        }
    }

    @Override
    public ParcelFileDescriptor openWrite(String name, long offsetBytes, long lengthBytes) throws RemoteException {
        try {
            return openWriteInternal(name, offsetBytes, lengthBytes);
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }
    }

    private void assertPreparedAndNotSealed(String cookie) {
        synchronized (mLock) {
            if (!mPrepared) {
                throw new IllegalStateException(cookie + " before prepared");
            }
            if (mSealed) {
                throw new SecurityException(cookie + " not allowed after commit");
            }
        }
    }


    private ParcelFileDescriptor openWriteInternal(String name, long offsetBytes, long lengthBytes)
            throws IOException {
        // Quick sanity check of state, and allocate a pipe for ourselves. We
        // then do heavy disk allocation outside the lock, but this open pipe
        // will block any attempted install transitions.
        final FileBridge bridge;
        synchronized (mLock) {
            assertPreparedAndNotSealed("openWrite");

            bridge = new FileBridge();
            mBridges.add(bridge);
        }
        try {

View on GitHub (pinned to 666fefcb5d)