MuntashirAkon/AppManager · error · IllegalArgumentException

Input must contain one or more user handles

Error message

Input must contain one or more user handles

What it means

The RulesImporter constructor requires at least one Android user handle because rules are imported per-user into per-user ComponentsBlocker instances. An empty int[] userIds cannot satisfy that, so it throws IllegalArgumentException immediately.

Solutions

  1. Pass at least one valid user ID, e.g. the current user: new int[]{UserHandle.myUserId()}
  2. Fix user-list construction so filtered results never silently yield an empty array
  3. Validate userIds.length > 0 at the call site (UI level) before constructing RulesImporter

Example fix

// before
importer = new RulesImporter(types, selectedUsers); // selectedUsers may be empty
// after
if (selectedUsers.length == 0) {
    selectedUsers = new int[]{UserHandle.myUserId()};
}
importer = new RulesImporter(types, selectedUsers);
Defensive patterns

Strategy: validation

Validate before calling

if (userIds == null || userIds.length == 0) {
    userIds = new int[]{UserHandle.myUserId()};
}

Type guard

boolean hasUsers(int[] ids) {
    return ids != null && ids.length > 0;
}

Try / catch

try {
    importer = new RulesImporter(types, userIds);
} catch (IllegalArgumentException e) {
    showError("Select at least one user for import");
}

Prevention

When it happens

Trigger: new RulesImporter(typesToImport, new int[0]) — e.g. when the caller built the user list by filtering and all users were excluded, or passed an uninitialized array.

Common situations: Import UI invoked on a single-user device but with a user-selection bug; work profile removed between listing users and starting the import; hardcoded empty arrays in scripts/tests.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at app/src/main/java/io/github/muntashirakon/AppManager/rules/RulesImporter.java:47

 * <br>
 * Format: <code>package_name component_name type mode|is_applied|is_granted</code>
 *
 * @see RulesExporter
 * @see RuleType
 */
public class RulesImporter implements Closeable {
    @NonNull
    private final HashMap<String, ComponentsBlocker>[] mComponentsBlockers;
    @NonNull
    private final List<RuleType> mTypesToImport;
    @Nullable
    private List<String> mPackagesToImport;
    @NonNull
    private final int[] mUserIds;

    public RulesImporter(@NonNull List<RuleType> typesToImport, @NonNull int[] userIds) {
        if (userIds.length == 0) {
            throw new IllegalArgumentException("Input must contain one or more user handles");
        }
        // Init CBs
        //noinspection unchecked
        mComponentsBlockers = new HashMap[userIds.length];
        for (int i = 0; i < userIds.length; ++i) {
            mComponentsBlockers[i] = new HashMap<>();
        }
        mTypesToImport = typesToImport;
        mUserIds = userIds;
    }

    public void addRulesFromUri(Uri uri) throws IOException {
        try (InputStream inputStream = ContextUtils.getContext().getContentResolver().openInputStream(uri)) {
            if (inputStream == null) throw new IOException("Content provider has crashed.");
            try (BufferedReader TSVFile = new BufferedReader(new InputStreamReader(inputStream))) {
                String dataRow;
                while ((dataRow = TSVFile.readLine()) != null) {
                    RuleEntry entry = RuleEntry.unflattenFromString(null, dataRow, true);

View on GitHub (pinned to 0152f468fc)