MuntashirAkon/AppManager · error · PermissionException

Unmodifiable permission

Error message

Unmodifiable permission ${permissionName}

What it means

AppOpPermissionController.requireModifiable() checks isModifiable(permission) before grant/revoke; permissions that the controller is not allowed to change (e.g. platform-managed or protected permissions) throw PermissionException('Unmodifiable permission ...').

Solutions

  1. Check isModifiable(permission) (or the permission's flags) before calling grant/revoke and skip non-modifiable ones
  2. Restrict the operation to permissions the controller supports
  3. If the permission truly should be changeable, run with sufficient privileges (root/adb) or use the appropriate platform mechanism

Example fix

// before
controller.revoke(permission, reason); // may throw for fixed permissions
// after
if (controller.isModifiable(permission)) {
    controller.revoke(permission, reason);
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!controller.isModifiable(permission)) {
    skip.add(permission); // don't call grant/revoke
}

Try / catch

try {
    controller.grant(permission);
} catch (PermissionException e) {
    Log.w(TAG, "Skipping unmodifiable permission " + permission.getName(), e);
}

Prevention

When it happens

Trigger: Calling grant() or revoke() on a Permission for which isModifiable() returns false — typically permissions owned/enforced by the system rather than this controller.

Common situations: Trying to revoke permissions that Android marks as fixed or development-only; batch-applying overrides to every declared permission without filtering; targeting privileged/system apps.

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/9a3d7bae912ffb87. Report an issue: GitHub.

Appendix: source

Thrown at app/src/main/java/io/github/muntashirakon/AppManager/permission/AppOpPermissionController.java:184

            }
            boolean killApp = permission.isAppOpAllowed() != granted
                    && (permission.readOnly || legacyRuntime);
            if (!permission.isReadOnly() && !legacyRuntime) {
                permission.setGranted(granted);
            }
            permission.setAppOpAllowed(granted);
            persist(packageInfo.applicationInfo, permission, appOpsManager, null, false);
            killIfNeeded(packageInfo.applicationInfo.uid, killApp);
            return PermissionChangeResult.success();
        } catch (Exception 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 killIfNeeded(int uid, boolean killApp) throws PermissionException {
        if (!killApp || !mAppOpPlatform.canKillUid()) {
            return;
        }
        try {
            mAppOpPlatform.killUid(uid, KILL_REASON_APP_OP_CHANGE);
        } catch (Exception e) {
            throw new PermissionException(e);
        }
    }

    private void persist(@NonNull ApplicationInfo applicationInfo,
                         @NonNull Permission permission,
                         @NonNull AppOpsManagerCompat appOpsManager,
                         @Nullable String revokeReason) throws PermissionException {

View on GitHub (pinned to 0152f468fc)