MuntashirAkon/AppManager · error · UnsupportedOperationException

Invalid key ${key}

Error message

Invalid key ${key}

What it means

SignatureOption.test() evaluates whether a package's signing info matches a filter criterion by switching on the option's key (subject starts-with, ends-with, regex, sha256, etc.). If the key is unrecognized it throws UnsupportedOperationException('Invalid key ...'), since test() cannot decide a match for an unknown criterion.

Source

Thrown at app/src/main/java/io/github/muntashirakon/AppManager/filters/options/SignatureOption.java:137

                    if (regexValue.matcher(subject).matches()) {
                        matchedSubjectLines.add(subject);
                    }
                }
                return result.setMatched(!matchedSubjectLines.isEmpty())
                        .setMatchedSubjectLines(matchedSubjectLines);
            }
            case "sha256": {
                String[] sha256sums = info.getSignatureSha256Checksums();
                for (int i = 0; i < sha256sums.length; ++i) {
                    if (sha256sums[i].equals(value)) {
                        return result.setMatched(true)
                                .setMatchedSubjectLines(Collections.singletonList(info.getSignatureSubjectLines()[i]));
                    }
                }
                return result.setMatched(false).setMatchedSubjectLines(Collections.emptyList());
            }
            default:
                throw new UnsupportedOperationException("Invalid key " + key);
        }
    }

    @NonNull
    @Override
    public CharSequence toLocalizedString(@NonNull Context context) {
        SpannableStringBuilder sb = new SpannableStringBuilder("Signatures");
        switch (key) {
            case KEY_ALL:
                return sb.append(LangUtils.getSeparatorString()).append("any");
            case "no_signer":
                return sb.append(LangUtils.getSeparatorString()).append("none");
            case "with_lineage":
                return sb.append(" with lineages");
            case "without_lineage":
                return sb.append(" without lineages");
            case "with_source_stamp":
                return sb.append(" with source stamps");

View on GitHub (pinned to 0152f468fc)

Solutions

  1. Inspect the failing option's key and correct it to a supported key used in SignatureOption.test()
  2. Migrate/regenerate the persisted filter to the current key vocabulary
  3. Extend test() (and toLocalizedString) with the missing key if you intentionally added a new criterion

Example fix

// before
SignatureOption opt = new SignatureOption("subj_sw", value);
// after
SignatureOption opt = new SignatureOption("subject_starts_with", value); // supported key
Defensive patterns

Strategy: validation

Validate before calling

Set<String> validKeys = Set.of("subject_starts_with","subject_ends_with","sub_regex","sha256");
if (!validKeys.contains(opt.getKey())) throw new IllegalArgumentException("Bad signature filter key: " + opt.getKey());

Try / catch

try {
    matched = option.test(packageInfo);
} catch (UnsupportedOperationException e) {
    matched = false;
    Log.w(TAG, "Skipping filter with unknown key", e);
}

Prevention

When it happens

Trigger: Invoking test() on a SignatureOption whose key is not among the implemented case labels — typically from a stale or hand-crafted filter definition.

Common situations: Applying old saved filters after an upgrade that renamed keys; sharing filter rules between versions; typos in programmatically generated filters.

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