MuntashirAkon/AppManager · error · IllegalArgumentException

Invalid userId

Error message

Invalid userId 

What it means

checkCrossUserPermission validates the userId: USER_NULL is remapped to the current user, and only USER_ALL may otherwise be negative. Any other negative userId throws IllegalArgumentException("Invalid userId " + userId), guarding IPC callers that pass garbage user handles.

Source

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

                    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)) {
            return true;
        }
        if (requireFullPermission) {
            return checkSelfOrRemotePermission(ManifestCompat.permission.INTERACT_ACROSS_USERS_FULL, callingUid);
        }
        return checkSelfOrRemotePermission(ManifestCompat.permission.INTERACT_ACROSS_USERS_FULL, callingUid)
                || checkSelfOrRemotePermission(ManifestCompat.permission.INTERACT_ACROSS_USERS, callingUid);
    }

    public static boolean isShell() {
        return Users.getSelfOrRemoteUid() == Ops.SHELL_UID;
    }

    public static boolean isSystem() {
        return Users.getSelfOrRemoteUid() == Ops.SYSTEM_UID;
    }

View on GitHub (pinned to 0152f468fc)

Solutions

  1. Resolve or validate the userId before calling: use UserHandleHidden.myUserId() when unknown.
  2. Only pass UserHandleHidden.USER_ALL for all-user queries; never other negative values.
  3. Sanitize userId values from untrusted inputs (extras, IPC) before passing them in.
  4. Catch IllegalArgumentException at the call site if the userId originates from user-provided data.

Example fix

// before
boolean allowed = SelfPermissions.checkCrossUserPermission(userId, false);
// after
if (userId == UserHandleHidden.USER_NULL) userId = UserHandleHidden.myUserId();
if (userId < 0 && userId != UserHandleHidden.USER_ALL) {
    throw new IllegalArgumentException("Cannot check cross-user permission for userId " + userId);
}
boolean allowed = SelfPermissions.checkCrossUserPermission(userId, false);
Defensive patterns

Strategy: validation

Validate before calling

if (userId == UserHandleHidden.USER_NULL) userId = UserHandleHidden.myUserId();
if (userId < 0 && userId != UserHandleHidden.USER_ALL) {
    throw new IllegalArgumentException("Refusing to call with userId " + userId);
}
boolean allowed = SelfPermissions.checkCrossUserPermission(userId, requireFullPermission, callingUid);

Type guard

static boolean isValidUserId(int userId) {
    return userId >= 0 || userId == UserHandleHidden.USER_ALL;
}

Prevention

When it happens

Trigger: Calling checkCrossUserPermission (directly or via the 2-arg overload) with a userId that is negative and not UserHandleHidden.USER_ALL — typically an uninitialized userId field or a malformed value decoded from intent/bundle extras.

Common situations: Passing an uninitialized userId variable, decoding malformed IPC/intent data, mixing USER_NULL semantics across Android versions, calling from a context where myUserId() yields an unexpected value.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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