MuntashirAkon/AppManager · error · PermissionException

Unmodifiable permission

Error message

Unmodifiable permission ${permissionName}

What it means

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.

Solutions

  1. Filter the permission list with isModifiable() before attempting grant/revoke
  2. Check the permission's flags (PROTECTION flags / fixed flags) client-side and skip protected ones
  3. Use a privileged path (root/adb pm grant|revoke) if the intent is to override a fixed permission

Example fix

// before
controller.grant(permission); // throws for fixed permissions
// after
if (controller.isModifiable(permission)) {
    controller.grant(permission);
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!controller.isModifiable(permission)) {
    skipped.add(permission.getName());
} else {
    controller.grant(permission);
}

Try / catch

try {
    controller.revoke(permission, reason);
} catch (PermissionException e) {
    Log.w(TAG, "Cannot modify " + permission.getName(), e);
}

Prevention

When it happens

Trigger: Granting or revoking a permission that this PackageManager-based controller flags as non-modifiable (system-fixed, policy-fixed, or otherwise protected).

Common situations: Bulk-granting or bulk-revoking all declared permissions of a system app; overriding permissions fixed by device policy or the system.

Understand the failure class

Background: "You do not have permission" / 403 Forbidden errors: authenticated but not allowed — causes and fixes across open-source libraries — this error's family across 31 libraries.

Related errors


AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12). Data as JSON: /api/errors/265b33824cbb6d29. Report an issue: GitHub.

Appendix: source

Thrown at app/src/main/java/io/github/muntashirakon/AppManager/permission/PackageManagerPermissionController.java:190

            return PermissionChangeResult.unsupported("Unmodifiable permission " + permissionName);
        }
        if (!mPlatform.canModifyPermissions()) {
            return PermissionChangeResult.unsupported(
                    "Package Manager permission capability is unavailable");
        }
        permission.setGranted(granted);
        try {
            persist(packageInfo.applicationInfo, permission, null, false);
            return PermissionChangeResult.success();
        } catch (PermissionException e) {
            return PermissionChangeResult.failure("Could not change permission " + permissionName,
                    e);
        }
    }

    private void requireModifiable(@NonNull Permission permission) throws PermissionException {
        if (!isModifiable(permission)) {
            throw new PermissionException("Unmodifiable permission " + permission.getName());
        }
    }

    private void persist(@NonNull ApplicationInfo applicationInfo,
                         @NonNull Permission permission,
                         @Nullable String revokeReason) throws PermissionException {
        persist(applicationInfo, permission, revokeReason, true);
    }

    private void persist(@NonNull ApplicationInfo applicationInfo,
                         @NonNull Permission permission,
                         @Nullable String revokeReason,
                         boolean updatePermissionFlags) throws PermissionException {
        int userId = UserHandleHidden.getUserId(applicationInfo.uid);
        try {
            if (permission.isGranted()) {
                mPlatform.grantPermission(applicationInfo.packageName, permission.getName(), userId);
                Log.d("PERM", "Granted %s", permission.getName());

View on GitHub (pinned to 0152f468fc)