{"record":{"id":"afafa1525962d043","repo":"Universal-Debloater-Alliance/universal-android-debloater-next-generation","slug":"uad-list-type-must-be-selected","errorCode":null,"errorMessage":"UAD-list type must be selected","messagePattern":"UAD-list type must be selected","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/uad-gui/src/views/list.rs","lineNumber":743,"sourceCode":"                column![\n                    title_ctn,\n                    container(recap_view).padding(10),\n                    selected_pkgs_ctn,\n                    modal_btn_row,\n                ]\n                .spacing(10)\n                .align_x(Alignment::Center)\n            },\n        )\n        .width(900)\n        .height(Length::Shrink)\n        .max_height(700)\n        .style(style::Container::Background)\n        .into()\n    }\n\n    fn filter_package_lists(&mut self) {\n        let list_filter: UadList = self.selected_list.expect(\"UAD-list type must be selected\");\n        let package_filter: PackageState = self\n            .selected_package_state\n            .expect(\"pack-state must be selected\");\n        let removal_filter: Removal = self\n            .selected_removal\n            .expect(\"removal recommendation must be selected\");\n\n        self.filtered_packages = self.phone_packages\n            [self.selected_user.expect(\"User must be selected\").index]\n            .iter()\n            // we must filter the indices associated with pack-rows,\n            // that's why `enumerate` is before `filter`.\n            .enumerate()\n            .filter(|(_, p)| {\n                (list_filter == UadList::All || p.list == list_filter)\n                    && (package_filter == PackageState::All || p.state == package_filter)\n                    && (removal_filter == Removal::All || p.removal == removal_filter)\n                    && (self.input_value.is_empty()","sourceCodeStart":725,"sourceCodeEnd":761,"githubUrl":"https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/64465c850c7ed36329e67165ac08501abffb218e/crates/uad-gui/src/views/list.rs#L725-L761","documentation":"filter_package_lists in the list view unwraps `self.selected_list` (an Option<UadList>) with `.expect(\"UAD-list type must be selected\")`, assuming the dropdown always has a selection before filtering runs. If the filter routine executes before view initialization populated selected_list, or after a reset cleared it, the GUI panics during message handling.","triggerScenarios":"Calling filter_package_lists when selected_list is None: the list view is refreshed/re-rendered before the UadList dropdown is initialized, a state reset (device change, view switch) cleared the selection while filtering is still triggered, or a programmatic update sends a filter message without a selection.","commonSituations":"Switching devices or views so quickly that the filter runs against a not-yet-initialized dropdown; restoring saved settings that omit the list-type selection; a code change that initializes dropdowns lazily.","solutions":["Initialize selected_list with a default (e.g. UadList::All or the first enum variant) at view construction so it is never None.","Guard with `let Some(list_filter) = self.selected_list else { return }` and skip filtering until a selection exists.","Trigger filter_package_lists only from change events on the dropdown, never from generic view refresh paths.","Persist and restore the selected filter values with the rest of the settings state."],"exampleFix":"// before\nlet list_filter: UadList = self.selected_list.expect(\"UAD-list type must be selected\");\n// after\nlet Some(list_filter) = self.selected_list else { return };","handlingStrategy":"type-guard","validationCode":"if self.selected_list.is_none() || self.selected_package_state.is_none() || self.selected_removal.is_none() {\n    eprintln!(\"filters not initialized; skipping package list filter\");\n    return;\n}","typeGuard":"fn filters_ready(view: &ListView) -> bool {\n    view.selected_list.is_some() && view.selected_package_state.is_some() && view.selected_removal.is_some()\n}","tryCatchPattern":"let Some(list_filter) = self.selected_list else { return }; // early-return instead of expect","preventionTips":["Initialize all filter dropdowns with defaults at view construction so Options are never None.","Only run filtering from dropdown change events, not generic refresh paths.","Reset all filter selections together, never individually."],"tags":["panic","gui","state","null-safety"],"backgroundTag":"null-argument","analyzedSha":"64465c850c7ed36329e67165ac08501abffb218e","analyzedAt":"2026-09-12T09:09:23.137Z","contentChangedAt":"2026-09-12T09:09:23.137Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}