MuntashirAkon/AppManager · error · PermissionException
Legacy app cannot have not-granted runtime permission ${perm
Error message
Legacy app cannot have not-granted runtime permission ${permissionName} What it means
App Manager's permission module enforces an invariant for legacy apps (targetSdk <= 22): such apps do not use Android runtime permissions, so a runtime permission on a legacy app must always be marked granted. When prepareGrant or prepareRevoke encounters a runtime permission that is not granted on a legacy app, it throws PermissionException because the package state contradicts what the platform allows.
Source
Thrown at app/src/main/java/io/github/muntashirakon/AppManager/permission/PermissionMutation.java:154
// Disabling an AppOp may leave a legacy app holding state it should no longer
// access. Restarting it matches the existing runtime-permission behaviour.
killApp = true;
}
// Mark that the permission remains granted only for compatibility.
if (!permission.isRevokedCompat()) {
permission.setRevokedCompat(true);
}
}
}
return killApp;
}
private static void ensureLegacyRuntimePermissionIsGranted(@NonNull Permission permission)
throws PermissionException {
if (permission.isRuntime() && !permission.isGranted()) {
throw new PermissionException("Legacy app cannot have not-granted runtime permission "
+ permission.getName());
}
}
private static boolean supportsRuntimePermissions(@NonNull PackageInfo packageInfo) {
return packageInfo.applicationInfo.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1;
}
}
View on GitHub (pinned to 0152f468fc)
Solutions
- Re-check how the Permission object was constructed; ensure granted state is read from the platform for the correct user before mutation
- Skip mutation of runtime permissions for apps with targetSdkVersion <= 22, since legacy apps grant at install time
- If the state is genuinely inconsistent, reinstall or clear/re-grant the permission via system settings so the platform state matches
- Update the exported rules file so legacy apps only reference install-time permissions
Example fix
// before
permissionController.prepareGrant(permission);
// after
if (packageInfo.applicationInfo.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
permissionController.prepareGrant(permission);
} Defensive patterns
Strategy: validation
Validate before calling
if (permission.isRuntime() && !permission.isGranted()
&& packageInfo.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1) {
throw new IllegalStateException("Legacy app with ungranted runtime permission: " + permission.getName());
} Type guard
boolean isLegacyApp(PackageInfo info) {
return info.applicationInfo == null
|| info.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1;
} Try / catch
try {
permissionController.prepareGrant(permission);
} catch (PermissionException e) {
Log.w(TAG, "Skipping permission for legacy app", e);
} Prevention
- Check targetSdkVersion before mutating runtime permissions
- Refresh permission granted state from the platform immediately before mutation
- Exclude legacy apps from runtime-permission rule imports
When it happens
Trigger: Calling prepareGrant or prepareRevoke on a PackageInfo whose applicationInfo.targetSdkVersion <= LOLLIPOP_MR1 while the Permission object reports isRuntime() == true and isGranted() == false.
Common situations: Importing or mutating permission rules exported from a newer-device backup and applying them to a legacy (targetSdk 21-22) app; corrupted or hand-edited permission dumps; device-odexed data restored from a different Android version.
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
- Could not delete the selected backups
- An uninstallation was necessary but couldn't perform it.
- Could not create package staging directory
- Failed to restore the KeyStore files.
- Failed to rename KeyStore files
AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12).
Data as JSON: /api/errors/1597c8600d176eba.
Report an issue: GitHub.