MuntashirAkon/AppManager · error · UnsupportedOperationException

Invalid key ${key}

Error message

Invalid key ${key}

What it means

MinSdkOption.test matches an application's minimum SDK against the configured comparison by switching on key ('eq', 'le', 'ge'). An unrecognized key reaches the default branch and throws UnsupportedOperationException 'Invalid key <key>'. The filter's comparison key is not a valid MinSdk operator.

Source

Thrown at app/src/main/java/io/github/muntashirakon/AppManager/filters/options/MinSdkOption.java:53

    }

    @NonNull
    @Override
    public TestResult test(@NonNull IFilterableAppInfo info, @NonNull TestResult result) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
            return result.setMatched(true);
        }
        switch (key) {
            case KEY_ALL:
                return result.setMatched(true);
            case "eq":
                return result.setMatched(info.getMinSdk() == intValue);
            case "le":
                return result.setMatched(info.getMinSdk() <= intValue);
            case "ge":
                return result.setMatched(info.getMinSdk() >= intValue);
            default:
                throw new UnsupportedOperationException("Invalid key " + key);
        }
    }

    @NonNull
    @Override
    public CharSequence toLocalizedString(@NonNull Context context) {
        SpannableStringBuilder sb = new SpannableStringBuilder("Minimum SDK");
        switch (key) {
            case KEY_ALL:
                return sb.append(LangUtils.getSeparatorString()).append("any");
            case "eq":
                return sb.append(" = ").append(Integer.toString(intValue));
            case "le":
                return sb.append(" ≤ ").append(Integer.toString(intValue));
            case "ge":
                return sb.append(" ≥ ").append(Integer.toString(intValue));
            default:
                throw new UnsupportedOperationException("Invalid key " + key);

View on GitHub (pinned to 0152f468fc)

Solutions

  1. Change the key in the filter config to 'eq', 'le', or 'ge'.
  2. Re-create the filter via the app UI.
  3. Update/downgrade App Manager so the key set matches the one that created the filter.
  4. Validate the key when constructing the option; fail fast with a clear message.

Example fix

// before
new MinSdkOption("min_sdk", "<=", 24);
// after
new MinSdkOption("min_sdk", "le", 24);
Defensive patterns

Strategy: validation

Validate before calling

Set<String> VALID = Set.of("eq", "le", "ge");
if (!VALID.contains(option.getKey())) throw new IllegalArgumentException("Unsupported min_sdk key: " + option.getKey());

Type guard

boolean isValidKey(String k) { return "eq".equals(k) || "le".equals(k) || "ge".equals(k); }

Try / catch

try { matched = option.test(info); } catch (UnsupportedOperationException e) { Log.w(TAG, e.getMessage()); matched = false; }

Prevention

When it happens

Trigger: Calling test() on a MinSdkOption whose key is not exactly 'eq', 'le', or 'ge' — typically from a deserialized filter file with a typo, a renamed key across versions, or an operator borrowed from another option type.

Common situations: Hand-edited filter JSON using '<' or '<=' instead of 'le'; copying a key from a different filter option (e.g. 'before'); filters shared between app versions with differing key sets.

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/e57e0b7cd96df194. Report an issue: GitHub.