MuntashirAkon/AppManager · error · IllegalStateException

Unknown AppOpsManager mode

Error message

Unknown AppOpsManager mode 

What it means

checkStoragePermission checks the result of an AppOpsManager operation and only knows MODE_ALLOWED, MODE_ERRORED and MODE_IGNORED. If the system returns any other AppOpsManager mode (e.g. MODE_DEFAULT), it throws IllegalStateException("Unknown AppOpsManager mode " + opMode).

Solutions

  1. Handle MODE_DEFAULT explicitly by falling back to checkSelfOrRemotePermission instead of throwing.
  2. Log the unknown opMode and treat it conservatively (deny) rather than crashing.
  3. Update the switch to cover all AppOpsManager.MODE_* constants for the target SDK.
  4. Reproduce and test on the specific ROM/Android version that returns the unknown mode.

Example fix

// before
default:
    throw new IllegalStateException("Unknown AppOpsManager mode " + opMode);
// after
case AppOpsManager.MODE_DEFAULT:
    return checkSelfOrRemotePermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, callingUid);
default:
    return false;
Defensive patterns

Strategy: try-catch

Validate before calling

int opMode = appOps.checkOpNoThrow(op, uid, packageName);
if (opMode != AppOpsManager.MODE_ALLOWED
        && opMode != AppOpsManager.MODE_ERRORED
        && opMode != AppOpsManager.MODE_IGNORED
        && opMode != AppOpsManager.MODE_DEFAULT) {
    // unknown mode: skip the AppOps path and use a plain permission check
}

Try / catch

try {
    hasStorage = SelfPermissions.checkStoragePermission(callingUid);
} catch (IllegalStateException e) {
    hasStorage = ContextCompat.checkSelfPermission(ctx, Manifest.permission.WRITE_EXTERNAL_STORAGE)
            == PackageManager.PERMISSION_GRANTED;
}

Prevention

When it happens

Trigger: Calling checkStoragePermission on an Android version/ROM where AppOpsManager returns MODE_DEFAULT or a vendor-specific mode for the storage op, e.g. when the op was never explicitly set for the calling uid.

Common situations: Running on modified/OEM ROMs with non-standard AppOps behavior, Android version changes that reinterpret AppOps modes, uids whose storage op has only the default mode.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at app/src/main/java/io/github/muntashirakon/AppManager/self/SelfPermissions.java:216

    public static boolean checkStoragePermission() {
        int callingUid = Users.getSelfOrRemoteUid();
        if (callingUid == Ops.ROOT_UID) {
            return true;
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            String packageName = getCallingPackage(callingUid);
            AppOpsManagerCompat appOps = new AppOpsManagerCompat();
            int opMode = appOps.checkOpNoThrow(AppOpsManagerHidden.OP_MANAGE_EXTERNAL_STORAGE, callingUid, packageName);
            switch (opMode) {
                case AppOpsManager.MODE_DEFAULT:
                    return checkSelfOrRemotePermission(Manifest.permission.MANAGE_EXTERNAL_STORAGE, callingUid);
                case AppOpsManager.MODE_ALLOWED:
                    return true;
                case AppOpsManager.MODE_ERRORED:
                case AppOpsManager.MODE_IGNORED:
                    return false;
                default:
                    throw new IllegalStateException("Unknown AppOpsManager mode " + opMode);
            }
        }
        return checkSelfOrRemotePermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, callingUid);
    }

    public static boolean checkCrossUserPermission(@UserIdInt int userId, boolean requireFullPermission) {
        int callingUid = Users.getSelfOrRemoteUid();
        return checkCrossUserPermission(userId, requireFullPermission, callingUid);
    }

    public static boolean checkCrossUserPermission(@UserIdInt int userId, boolean requireFullPermission, int callingUid) {
        if (userId == UserHandleHidden.USER_NULL) {
            userId = UserHandleHidden.myUserId();
        }
        if (userId < 0 && userId != UserHandleHidden.USER_ALL) {
            throw new IllegalArgumentException("Invalid userId " + userId);
        }
        if (isSystemOrRootOrShell(callingUid) || userId == UserHandleHidden.getUserId(callingUid)) {

View on GitHub (pinned to 0152f468fc)