{"record":{"id":"deafd202eb824a76","repo":"emilk/egui","slug":"app-mut-got-the-wrong-type-of-app","errorCode":null,"errorMessage":"app_mut got the wrong type of App","messagePattern":"app_mut got the wrong type of App","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/eframe/src/web/app_runner.rs","lineNumber":192,"sourceCode":"            .native_pixels_per_point = Some(super::native_pixels_per_point());\n        runner.input.raw.system_theme = super::system_theme();\n\n        Ok(runner)\n    }\n\n    pub fn egui_ctx(&self) -> &egui::Context {\n        &self.egui_ctx\n    }\n\n    /// Get mutable access to the concrete [`App`] we enclose.\n    ///\n    /// This will panic if your app does not implement [`App::as_any_mut`].\n    pub fn app_mut<ConcreteApp: 'static + App>(&mut self) -> &mut ConcreteApp {\n        self.app\n            .as_any_mut()\n            .expect(\"Your app must implement `as_any_mut`, but it doesn't\")\n            .downcast_mut::<ConcreteApp>()\n            .expect(\"app_mut got the wrong type of App\")\n    }\n\n    pub fn auto_save_if_needed(&mut self) {\n        let time_since_last_save = now_sec() - self.last_save_time;\n        if time_since_last_save > self.app.auto_save_interval().as_secs_f64() {\n            self.save();\n        }\n    }\n\n    pub fn save(&mut self) {\n        if self.app.persist_egui_memory() {\n            super::storage::save_memory(&self.egui_ctx);\n        }\n        if let Some(storage) = self.frame.storage_mut() {\n            self.app.save(storage);\n        }\n        self.last_save_time = now_sec();\n    }","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/emilk/egui/blob/441971a776322a482e371775219380eca812cfa9/crates/eframe/src/web/app_runner.rs#L174-L210","documentation":"AppRunner::app_mut downcasts the boxed App to a caller-chosen concrete type via App::as_any_mut. The .expect fires when the downcast_mut::<ConcreteApp>() returns None, i.e. the stored App instance is not actually of the requested type. The library panics because there is no way to return a typed reference safely when the caller names the wrong type.","triggerScenarios":"Calling runner.app_mut::<MyApp>() where the runner was created with a different concrete App type (or a wrapper/box type that doesn't downcast to MyApp), typically because as_any_mut returns self but the generic parameter doesn't match the constructed app.","commonSituations":"Copy-pasting app_mut calls from examples into a project whose App type was renamed; running multiple apps and passing the wrong runner; wrapping the App in a newtype that forwards as_any_mut incorrectly; using app_mut in tests with a mock app of a different type.","solutions":["Make the generic parameter of app_mut exactly the concrete type the runner was constructed with (e.g. app_mut::<MyApp>()).","Verify App::as_any_mut is implemented as `self` on the concrete app (#[inline] fn as_any_mut(&mut self) -> &mut dyn Any { self }), not on a wrapper.","Search for other constructions of the runner to find which App type is actually stored."],"exampleFix":"// before\nlet app = runner.app_mut::<OldApp>();\n// after\nlet app = runner.app_mut::<MyApp>();","handlingStrategy":"type-guard","validationCode":"fn app_is<T: 'static + App>(runner: &AppRunner) -> bool { runner.app().as_any().is::<T>() }","typeGuard":"fn as_concrete<T: 'static + App>(runner: &mut AppRunner) -> Option<&mut T> { runner.app_mut::<T>() }.ok()\n// safer: check first: runner.app().as_any().downcast_ref::<T>().is_some()","tryCatchPattern":"// Rust panics; use std::panic::catch_unwind only at integration boundaries, otherwise ensure the concrete type via downcast_ref check before app_mut.","preventionTips":["Always pass the exact concrete App type used to construct the runner.","Implement as_any_mut as `self` on the concrete App only.","Add a debug_assert using downcast_ref before calling app_mut in test code."],"tags":["rust","downcast","panic","eframe"],"backgroundTag":"type-mismatch","analyzedSha":"441971a776322a482e371775219380eca812cfa9","analyzedAt":"2026-09-12T04:29:21.500Z","contentChangedAt":"2026-09-12T04:29:21.500Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}