{"record":{"id":"265b33824cbb6d29","repo":"MuntashirAkon/AppManager","slug":"unmodifiable-permission-permissionname-265b33","errorCode":null,"errorMessage":"Unmodifiable permission ${permissionName}","messagePattern":"Unmodifiable permission (.+?)","errorType":"exception","errorClass":"PermissionException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/permission/PackageManagerPermissionController.java","lineNumber":190,"sourceCode":"            return PermissionChangeResult.unsupported(\"Unmodifiable permission \" + permissionName);\n        }\n        if (!mPlatform.canModifyPermissions()) {\n            return PermissionChangeResult.unsupported(\n                    \"Package Manager permission capability is unavailable\");\n        }\n        permission.setGranted(granted);\n        try {\n            persist(packageInfo.applicationInfo, permission, null, false);\n            return PermissionChangeResult.success();\n        } catch (PermissionException e) {\n            return PermissionChangeResult.failure(\"Could not change permission \" + permissionName,\n                    e);\n        }\n    }\n\n    private void requireModifiable(@NonNull Permission permission) throws PermissionException {\n        if (!isModifiable(permission)) {\n            throw new PermissionException(\"Unmodifiable permission \" + permission.getName());\n        }\n    }\n\n    private void persist(@NonNull ApplicationInfo applicationInfo,\n                         @NonNull Permission permission,\n                         @Nullable String revokeReason) throws PermissionException {\n        persist(applicationInfo, permission, revokeReason, true);\n    }\n\n    private void persist(@NonNull ApplicationInfo applicationInfo,\n                         @NonNull Permission permission,\n                         @Nullable String revokeReason,\n                         boolean updatePermissionFlags) throws PermissionException {\n        int userId = UserHandleHidden.getUserId(applicationInfo.uid);\n        try {\n            if (permission.isGranted()) {\n                mPlatform.grantPermission(applicationInfo.packageName, permission.getName(), userId);\n                Log.d(\"PERM\", \"Granted %s\", permission.getName());","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/permission/PackageManagerPermissionController.java#L172-L208","documentation":"PackageManagerPermissionController.requireModifiable() is a precheck called by grant() and revoke(); when isModifiable(permission) is false the controller refuses the change and throws PermissionException('Unmodifiable permission ...'), protecting permissions it cannot safely persist.","triggerScenarios":"Granting or revoking a permission that this PackageManager-based controller flags as non-modifiable (system-fixed, policy-fixed, or otherwise protected).","commonSituations":"Bulk-granting or bulk-revoking all declared permissions of a system app; overriding permissions fixed by device policy or the system.","solutions":["Filter the permission list with isModifiable() before attempting grant/revoke","Check the permission's flags (PROTECTION flags / fixed flags) client-side and skip protected ones","Use a privileged path (root/adb pm grant|revoke) if the intent is to override a fixed permission"],"exampleFix":"// before\ncontroller.grant(permission); // throws for fixed permissions\n// after\nif (controller.isModifiable(permission)) {\n    controller.grant(permission);\n}","handlingStrategy":"try-catch","validationCode":"if (!controller.isModifiable(permission)) {\n    skipped.add(permission.getName());\n} else {\n    controller.grant(permission);\n}","typeGuard":null,"tryCatchPattern":"try {\n    controller.revoke(permission, reason);\n} catch (PermissionException e) {\n    Log.w(TAG, \"Cannot modify \" + permission.getName(), e);\n}","preventionTips":["Check permission flags (system/policy fixed) before changes","Batch operations should skip, not abort, on unmodifiable entries","Use pm grant/revoke via shell when overriding fixed permissions intentionally"],"tags":["java","android","permissions"],"backgroundTag":"insufficient-permissions","analyzedSha":"0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5","analyzedAt":"2026-09-12T14:03:37.243Z","contentChangedAt":"2026-09-12T14:03:37.243Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}