{"record":{"id":"205938566d601d36","repo":"MuntashirAkon/AppManager","slug":"invalid-key-key-backupoption","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/BackupOption.java","lineNumber":162,"sourceCode":"                    if ((backup.flags & intValue) == intValue) {\n                        matchedBackups.add(backup);\n                    }\n                }\n                return result.setMatched(!matchedBackups.isEmpty())\n                        .setMatchedBackups(matchedBackups);\n            }\n            case \"without_flags\": {\n                List<Backup> matchedBackups = new ArrayList<>();\n                for (Backup backup : backups) {\n                    if ((backup.flags & intValue) != intValue) {\n                        matchedBackups.add(backup);\n                    }\n                }\n                return result.setMatched(!matchedBackups.isEmpty())\n                        .setMatchedBackups(matchedBackups);\n            }\n            default:\n                throw new UnsupportedOperationException(\"Invalid key \" + key);\n        }\n    }\n\n\n    @NonNull\n    @Override\n    public CharSequence toLocalizedString(@NonNull Context context) {\n        SpannableStringBuilder sb = new SpannableStringBuilder();\n        switch (key) {\n            case KEY_ALL:\n                return \"Apps with or without backups\";\n            case \"backups\":\n                return \"Only the apps with backups\";\n            case \"no_backups\":\n                return \"only the apps without backups\";\n            case \"latest_backup\":\n                return \"Only the apps having the latest backups\";\n            case \"outdated_backup\":","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/filters/options/BackupOption.java#L144-L180","documentation":"BackupOption.test() evaluates a PackageInfo against the configured key; if key is not one of the recognized cases (has_backup, backups, with_flags, etc.) the default branch throws UnsupportedOperationException(\"Invalid key \" + key). It signals that the option was constructed with a key it cannot evaluate.","triggerScenarios":"Constructing BackupOption with an unrecognized key string and then calling test() during app-list filtering; saved filter configurations containing keys from a different AppManager version; typos in data-driven filter setup.","commonSituations":"After upgrading AppManager, old stored filters reference renamed keys; developer adds a new key to another option class and reuses it here; programmatic filter construction with hardcoded wrong key strings.","solutions":["Use only keys BackupOption's switch supports (e.g. \"has_backup\", \"no_backup\", \"backup_allowed\", \"backups\", \"with_flags\", \"without_flags\")","Add the missing case to test() if a new key was introduced","Clear or migrate saved filters that carry stale keys","Validate user-chosen keys against the supported list before constructing the option"],"exampleFix":"// before\nFilterOption opt = new BackupOption(\"backup\", \"backup_exists\"); // unknown key\nboolean m = opt.test(packageInfo).isMatched(); // throws\n// after\nFilterOption opt = new BackupOption(\"backup\", \"has_backup\"); // supported key\nboolean m = opt.test(packageInfo).isMatched();","handlingStrategy":"type-guard","validationCode":"Set<String> VALID = Set.of(\"has_backup\",\"no_backup\",\"backup_allowed\",\"backups\",\"with_flags\",\"without_flags\"); if (!VALID.contains(key)) throw new IllegalArgumentException(\"Unsupported BackupOption key: \" + key);","typeGuard":"boolean isValidBackupKey(String key) { return key != null && Set.of(\"has_backup\",\"no_backup\",\"backup_allowed\",\"backups\",\"with_flags\",\"without_flags\").contains(key); }","tryCatchPattern":"try { boolean matched = option.test(packageInfo).isMatched(); } catch (UnsupportedOperationException e) { matched = false; /* skip unrecognizable filter */ }","preventionTips":["Use shared key constants instead of raw strings","Migrate or drop filters saved by older app versions before applying","Keep test()/toLocalizedString() key sets aligned","Validate exported filter JSON against the current schema on import"],"tags":["android","filters","backup","unsupported-key"],"backgroundTag":"unsupported-operation","analyzedSha":"0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5","analyzedAt":"2026-09-12T14:03:37.243Z","contentChangedAt":"2026-09-12T14:03:37.243Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}