{"record":{"id":"e4c2c0bcc9a54dd6","repo":"Universal-Debloater-Alliance/universal-android-debloater-next-generation","slug":"device-should-be-selected","errorCode":null,"errorMessage":"Device should be selected","messagePattern":"Device should be selected","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/uad-gui/src/gui.rs","lineNumber":254,"sourceCode":"                        {\n                            self.apps_view.update(\n                                &mut self.settings_view,\n                                &mut self.selected_device.clone().unwrap_or_default(),\n                                &mut self.update_state.uad_list,\n                                AppsMessage::RestoringDevice(output.clone()),\n                            );\n                        }\n                        if self.nb_running_async_adb_commands == 0 {\n                            return self.update(Message::RefreshButtonPressed);\n                        }\n                    }\n                    SettingsMessage::MultiUserMode(toggled) if toggled => {\n                        for user in self.apps_view.phone_packages.clone() {\n                            for (i, _) in user.iter().filter(|&pkg| pkg.selected).enumerate() {\n                                for u in self\n                                    .selected_device\n                                    .as_ref()\n                                    .expect(\"Device should be selected\")\n                                    .user_list\n                                    .iter()\n                                    .filter(|&u| !u.protected)\n                                {\n                                    self.apps_view.phone_packages[u.index][i].selected = true;\n                                }\n                            }\n                        }\n                    }\n                    _ => (),\n                }\n                self.settings_view\n                    .update(\n                        &self.selected_device.clone().unwrap_or_default(),\n                        &self.apps_view.phone_packages,\n                        &mut self.nb_running_async_adb_commands,\n                        msg,\n                        self.apps_view.selected_user,","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/64465c850c7ed36329e67165ac08501abffb218e/crates/uad-gui/src/gui.rs#L236-L272","documentation":"In UadGui::update, toggling MultiUserMode on iterates the selected device's user list, unwrapping `self.selected_device` with `.expect(\"Device should be selected\")`. The invariant assumed is that multi-user mode can only be toggled when a device is connected; if the toggle message arrives with no device selected (e.g. device disconnected mid-iteration or state desync), the GUI panics inside the update loop.","triggerScenarios":"Sending SettingsMessage::MultiUserMode(true) while self.selected_device is None: the device was unplugged/removed after the toggle was rendered, the GUI state was reset without clearing the settings view, or multi-user mode is toggled before any device connects.","commonSituations":"Toggling multi-user selection in the settings view right as the ADB device disconnects; resuming the app with stale settings state and no device attached; race between device list refresh and the toggle message.","solutions":["Replace .expect with a None guard: `if let Some(device) = &self.selected_device { ... }` (or `let Some(device) = ... else { return }`) so the toggle is a no-op without a device.","Disable the MultiUserMode toggle in the UI when no device is selected.","Clear/reset the multi-user toggle state whenever selected_device becomes None on device disconnect.","Log a warning when the message arrives deviceless to surface the state desync."],"exampleFix":"// before\nself.selected_device\n    .as_ref()\n    .expect(\"Device should be selected\")\n    .user_list\n// after\nlet Some(device) = self.selected_device.as_ref() else { return };\ndevice.user_list","handlingStrategy":"type-guard","validationCode":"// in the message handler, before touching the device\nif self.selected_device.is_none() {\n    eprintln!(\"MultiUserMode toggled with no device selected; ignoring\");\n    return;\n}","typeGuard":"fn device_selected(gui: &UadGui) -> bool { gui.selected_device.is_some() }","tryCatchPattern":"let Some(device) = self.selected_device.as_ref() else { return }; // then use device.user_list","preventionTips":["Guard every selected_device unwrap in GUI update paths with an early return.","Clear dependent toggles (multi-user mode) when the device disconnects.","Disable device-dependent UI controls while no device is selected."],"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"}