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
- Resolve or validate the userId before calling: use UserHandleHidden.myUserId() when unknown.
- Only pass UserHandleHidden.USER_ALL for all-user queries; never other negative values.
- Sanitize userId values from untrusted inputs (extras, IPC) before passing them in.
- 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
- Never pass raw userId values from untrusted extras/IPC without validation.
- Normalize USER_NULL to myUserId() before cross-user checks.
- Use UserHandleHidden.USER_ALL explicitly for all-user queries.
- Centralize userId sanitization in one utility so callers cannot skip it.
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
- Unknown density {densityName}
- Package name is missing.
- No splits selected.
- "manifest" has duplicate "application" tags.
- Android System (android) cannot be backed up.
AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12).
Data as JSON: /api/errors/95c0b94ce734e1ba.
Report an issue: GitHub.