emilk/egui · error
Your app must implement `as_any_mut`, but it doesn't
Error message
Your app must implement `as_any_mut`, but it doesn't
What it means
`AppRunner::app_mut<ConcreteApp>` requires the enclosed `App` to expose `&mut dyn Any` via `App::as_any_mut`; the `expect` panics when `as_any_mut()` returns `None`. This happens when a custom `App` implementation does not implement `as_any_mut` (e.g. returns `None` from a default/no-op impl), making the downcast to the concrete type impossible. eframe uses this for inspection/inspection plugins and for callers wanting typed access to their app.
Source
Thrown at crates/eframe/src/web/app_runner.rs:190
.entry(egui::ViewportId::ROOT)
.or_default()
.native_pixels_per_point = Some(super::native_pixels_per_point());
runner.input.raw.system_theme = super::system_theme();
Ok(runner)
}
pub fn egui_ctx(&self) -> &egui::Context {
&self.egui_ctx
}
/// Get mutable access to the concrete [`App`] we enclose.
///
/// This will panic if your app does not implement [`App::as_any_mut`].
pub fn app_mut<ConcreteApp: 'static + App>(&mut self) -> &mut ConcreteApp {
self.app
.as_any_mut()
.expect("Your app must implement `as_any_mut`, but it doesn't")
.downcast_mut::<ConcreteApp>()
.expect("app_mut got the wrong type of App")
}
pub fn auto_save_if_needed(&mut self) {
let time_since_last_save = now_sec() - self.last_save_time;
if time_since_last_save > self.app.auto_save_interval().as_secs_f64() {
self.save();
}
}
pub fn save(&mut self) {
if self.app.persist_egui_memory() {
super::storage::save_memory(&self.egui_ctx);
}
if let Some(storage) = self.frame.storage_mut() {
self.app.save(storage);
}View on GitHub (pinned to 441971a776)
Solutions
- Implement `as_any_mut` correctly: `fn as_any_mut(&mut self) -> Option<&mut dyn Any> { Some(self) }`.
- Verify the generic parameter matches the actual concrete app type (the second `expect` in the same function guards against type mismatch).
- Remove any manual `None` return or `panic!` stub left in `as_any_mut`.
- If you only need read access, use `app()`/`as_any` analogues — but still implement the method properly.
Example fix
// before
impl App for MyApp {
fn as_any_mut(&mut self) -> Option<&mut dyn Any> { None }
}
// after
use std::any::Any;
impl App for MyApp {
fn as_any_mut(&mut self) -> Option<&mut dyn Any> { Some(self) }
} Defensive patterns
Strategy: type-guard
Validate before calling
// Verify typed access works before calling app_mut
fn can_downcast_to<A: App + 'static>(runner: &AppRunner) -> bool {
runner.app.as_any().map_or(false, |a| a.is::<A>())
} Type guard
fn as_my_app<'a>(app: &'a mut dyn App) -> Option<&'a mut MyApp> {
app.as_any_mut()?.downcast_mut::<MyApp>()
} Try / catch
// eframe panics rather than returning Result, so guard first:
if let Some(my_app) = runner.app.as_any_mut().and_then(|a| a.downcast_mut::<MyApp>()) {
my_app.do_mutate();
} Prevention
- Always implement as_any_mut as Some(self) in App impls
- Never stub as_any_mut with None or panic!
- Match the generic type parameter to the actual concrete app type
When it happens
Trigger: Calling `runner.app_mut::<MyApp>()` (directly or via eframe features like inspection) when `MyApp`'s `as_any_mut` returns `None` because it was not implemented or was implemented to return `None`.
Common situations: Implementing `App` with an empty/`unimplemented!`-style `as_any_mut` stub; copying an old example where the trait method was optional; mixing trait objects so the downcast target type doesn't match the real concrete type.
Related errors
- app_mut got the wrong type of App
- Single-use AppCreator has unexpectedly already been taken
- failed to fit multisamples option of native_options into u8
- Failed to get window handle
- viewport doesn't exist
AI-assisted analysis of emilk/egui@441971a776 (2026-09-12).
Data as JSON: /api/errors/c1b2fcb397b84832.
Report an issue: GitHub.