Universal-Debloater-Alliance/universal-android-debloater-next-generation · error
UAD-list type must be selected
Error message
UAD-list type must be selected
What it means
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.
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.
Example fix
// before
let list_filter: UadList = self.selected_list.expect("UAD-list type must be selected");
// after
let Some(list_filter) = self.selected_list else { return }; Defensive patterns
Strategy: type-guard
Validate before calling
if self.selected_list.is_none() || self.selected_package_state.is_none() || self.selected_removal.is_none() {
eprintln!("filters not initialized; skipping package list filter");
return;
} Type guard
fn filters_ready(view: &ListView) -> bool {
view.selected_list.is_some() && view.selected_package_state.is_some() && view.selected_removal.is_some()
} Try / catch
let Some(list_filter) = self.selected_list else { return }; // early-return instead of expect Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Device should be selected
- pack-state must be selected
- {e}
- There must be 1 tab after serial
- There must be at least 1 ':'-separated component
AI-assisted analysis of Universal-Debloater-Alliance/universal-android-debloater-next-generation@64465c850c (2026-09-12).
Data as JSON: /api/errors/afafa1525962d043.
Report an issue: GitHub.
Appendix: source
Thrown at crates/uad-gui/src/views/list.rs:743
column![
title_ctn,
container(recap_view).padding(10),
selected_pkgs_ctn,
modal_btn_row,
]
.spacing(10)
.align_x(Alignment::Center)
},
)
.width(900)
.height(Length::Shrink)
.max_height(700)
.style(style::Container::Background)
.into()
}
fn filter_package_lists(&mut self) {
let list_filter: UadList = self.selected_list.expect("UAD-list type must be selected");
let package_filter: PackageState = self
.selected_package_state
.expect("pack-state must be selected");
let removal_filter: Removal = self
.selected_removal
.expect("removal recommendation must be selected");
self.filtered_packages = self.phone_packages
[self.selected_user.expect("User must be selected").index]
.iter()
// we must filter the indices associated with pack-rows,
// that's why `enumerate` is before `filter`.
.enumerate()
.filter(|(_, p)| {
(list_filter == UadList::All || p.list == list_filter)
&& (package_filter == PackageState::All || p.state == package_filter)
&& (removal_filter == Removal::All || p.removal == removal_filter)
&& (self.input_value.is_empty()View on GitHub (pinned to 64465c850c)