{"record":{"id":"48714c6396ded0fb","repo":"asLody/VirtualApp","slug":"not-allowed-after-commit","errorCode":null,"errorMessage":" not allowed after commit","messagePattern":" not allowed after commit","errorType":"exception","errorClass":"SecurityException","httpStatus":null,"severity":"error","filePath":"VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/installer/PackageInstallerSession.java","lineNumber":283,"sourceCode":"        }\n    }\n\n    @Override\n    public ParcelFileDescriptor openWrite(String name, long offsetBytes, long lengthBytes) throws RemoteException {\n        try {\n            return openWriteInternal(name, offsetBytes, lengthBytes);\n        } catch (IOException e) {\n            throw new IllegalStateException(e);\n        }\n    }\n\n    private void assertPreparedAndNotSealed(String cookie) {\n        synchronized (mLock) {\n            if (!mPrepared) {\n                throw new IllegalStateException(cookie + \" before prepared\");\n            }\n            if (mSealed) {\n                throw new SecurityException(cookie + \" not allowed after commit\");\n            }\n        }\n    }\n\n\n    private ParcelFileDescriptor openWriteInternal(String name, long offsetBytes, long lengthBytes)\n            throws IOException {\n        // Quick sanity check of state, and allocate a pipe for ourselves. We\n        // then do heavy disk allocation outside the lock, but this open pipe\n        // will block any attempted install transitions.\n        final FileBridge bridge;\n        synchronized (mLock) {\n            assertPreparedAndNotSealed(\"openWrite\");\n\n            bridge = new FileBridge();\n            mBridges.add(bridge);\n        }\n        try {","sourceCodeStart":265,"sourceCodeEnd":301,"githubUrl":"https://github.com/asLody/VirtualApp/blob/666fefcb5d3f39cc944001c3457c38ffd6544c87/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/installer/PackageInstallerSession.java#L265-L301","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Do not call openWrite/openRead after commit(); create a new session if more data must be staged.","Finish all writes and close all streams before calling commit().","If commit failed, abandon() the session, create a fresh one via createSession, and re-stage everything."],"exampleFix":"// before\nsession.commit(callback);\nOutputStream out = session.openWrite(\"split2.apk\", 0, -1); // SecurityException\n\n// after\ntry (OutputStream out = session.openWrite(\"split2.apk\", 0, -1)) {\n    out.write(splitBytes);\n}\nsession.commit(callback);","handlingStrategy":"try-catch","validationCode":"// Track commit state; never call openWrite/openRead after commit()\nif (committed) throw new IllegalStateException(\"Session already committed\");","typeGuard":null,"tryCatchPattern":"try {\n    stream = session.openWrite(name, offset, length);\n} catch (SecurityException e) {\n    if (String.valueOf(e.getMessage()).endsWith(\"not allowed after commit\")) {\n        // create a fresh session and re-stage\n    } else throw e;\n}","preventionTips":["Close all write streams before commit() (try-with-resources).","Mark session objects as committed in your wrapper and refuse further IO.","Recreate a new session instead of reusing a committed one."],"tags":["security-exception","package-installer","session-sealed","android"],"backgroundTag":"invalid-state-transition","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"}