{"record":{"id":"a831220b024a13a8","repo":"MuntashirAkon/AppManager","slug":"invalid-key-key-installedoption","errorCode":null,"errorMessage":"Invalid key ${key}","messagePattern":"Invalid key (.+?)","errorType":"validation","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/filters/options/InstalledOption.java","lineNumber":52,"sourceCode":"    }\n\n    @NonNull\n    @Override\n    public TestResult test(@NonNull IFilterableAppInfo info, @NonNull TestResult result) {\n        boolean installed = info.isInstalled();\n        switch (key) {\n            case KEY_ALL:\n                return result.setMatched(true);\n            case \"installed\":\n                return result.setMatched(installed);\n            case \"uninstalled\":\n                return result.setMatched(!installed);\n            case \"installed_before\":\n                return result.setMatched(installed && info.getFirstInstallTime() <= longValue);\n            case \"installed_after\":\n                return result.setMatched(installed && info.getFirstInstallTime() >= longValue);\n            default:\n                throw new UnsupportedOperationException(\"Invalid key \" + key);\n        }\n    }\n\n    @NonNull\n    @Override\n    public CharSequence toLocalizedString(@NonNull Context context) {\n        SpannableStringBuilder sb = new SpannableStringBuilder(\"Installed\");\n        switch (key) {\n            case KEY_ALL:\n                return sb.append(LangUtils.getSeparatorString()).append(\"any\");\n            case \"installed\":\n                return \"Installed apps\";\n            case \"uninstalled\":\n                return \"Uninstalled apps\";\n            case \"installed_before\":\n                return sb.append(\" before \").append(DateUtils.formatDateTime(context, longValue));\n            case \"installed_after\":\n                return sb.append(\" after \").append(DateUtils.formatDateTime(context, longValue));","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/filters/options/InstalledOption.java#L34-L70","documentation":"InstalledOption.test() switches over the configured key (all/installed/not_installed/installed_before/installed_after); any other key hits the default branch and throws UnsupportedOperationException. The key should have been validated by setKeyValue(), so this means the key state is inconsistent with the class's switch.","triggerScenarios":"A key present in InstalledOption's key map but missing a case in test()'s switch; direct modification of the protected `key` field; stale keys from hand-built Parcels or reflection.","commonSituations":"Adding a new install-related key without updating test(); forked builds with extra keys; deserialization of crafted data.","solutions":["Add a case for the key in InstalledOption.test()'s switch.","Set keys only through setKeyValue() for early validation.","Keep the key map and test() switch synchronized."],"exampleFix":"// before\ncase \"installed_after\":\n    return result.setMatched(installed && info.getFirstInstallTime() >= longValue);\ndefault:\n    throw new UnsupportedOperationException(\"Invalid key \" + key);\n// after\ncase \"installed_after\":\n    return result.setMatched(installed && info.getFirstInstallTime() >= longValue);\ncase \"new_key\":\n    return result.setMatched(/* logic */);\ndefault:\n    throw new UnsupportedOperationException(\"Invalid key \" + key);","handlingStrategy":"validation","validationCode":"if (!option.getKeysWithType().containsKey(option.getKey())) {\n    throw new IllegalStateException(\"Unrecognized key: \" + option.getKey());\n}","typeGuard":null,"tryCatchPattern":"try {\n    result = option.test(info, result);\n} catch (UnsupportedOperationException e) {\n    Log.w(TAG, \"Filter option key not supported\", e);\n    result.setMatched(false);\n}","preventionTips":["Keep the key map and test() switch in lockstep.","Assign keys only via setKeyValue().","Test all keys of each option class in CI."],"tags":["java","android","switch-statement","unsupported-operation"],"backgroundTag":"unsupported-operation","analyzedSha":"0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5","analyzedAt":"2026-09-12T14:03:37.243Z","contentChangedAt":"2026-09-12T14:03:37.243Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}