linebender/druid · error
Application state already borrowed
Error message
Application state already borrowed
What it means
`Application::run` stores its state in a `RefCell`. If `try_borrow_mut` fails, the state is already mutably borrowed (i.e. `run` is being re-entered or the state is borrowed elsewhere), so it panics to avoid aliased mutation of the application state.
Solutions
- Never call `Application::run` from inside an app handler or callback; let the outer `run` continue
- Ensure no code path borrows the application state while `run` executes
- Keep `run` on the main entry path and drive logic via the event loop/handler instead
Example fix
// before
fn on_command(&mut self, ...) {
self.app.run(None); // re-entrant borrow -> panic
}
// after
fn on_command(&mut self, ...) {
// handle logic via events; the outer run() loop keeps running
} Defensive patterns
Strategy: try-catch
Validate before calling
// Only call run from the top-level main function, never from handlers/callbacks
Try / catch
std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| app.run(handler))); // Prefer prevention: do not call run re-entrantly.
Prevention
- Never call `run` inside event handlers or callbacks
- Avoid holding borrows of application state across the run call
- Keep application lifecycle single-threaded and re-entrancy-free
When it happens
Trigger: Re-entrant call to `run` (directly or via a handler while the first `run` is still on the stack), or some other code holding a mutable borrow of the application's internal state cell.
Common situations: Calling `run` from within an event handler or a callback triggered by the running loop; accidentally re-entering `run` through recursion.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Application is already running
- There is no globally active Application
- Tried to build a window without setting the handler
- Unwrap named called on unnamed FieldIdent
- unexpected wayland event
AI-assisted analysis of linebender/druid@0f8b1195e4 (2026-09-10).
Data as JSON: /api/errors/0281c97d2904c336.
Report an issue: GitHub.
Appendix: source
Thrown at druid-shell/src/application.rs:135
/// Start the `Application` runloop.
///
/// The provided `handler` will be used to inform of events.
///
/// This will consume the `Application` and block the current thread
/// until the `Application` has finished executing.
///
/// # Panics
///
/// Panics if the `Application` is already running.
pub fn run(self, handler: Option<Box<dyn AppHandler>>) {
// Make sure this application hasn't run() yet.
if let Ok(mut state) = self.state.try_borrow_mut() {
if state.running {
panic!("Application is already running");
}
state.running = true;
} else {
panic!("Application state already borrowed");
}
// Run the platform application
self.backend_app.run(handler);
// This application is no longer active, so clear the global reference
GLOBAL_APP.with(|global_app| {
*global_app.borrow_mut() = None;
});
// .. and release the main thread
util::release_main_thread();
// .. and mark as done so a new sequence can start
APPLICATION_CREATED
.compare_exchange(true, false, Ordering::AcqRel, Ordering::Acquire)
.expect("Application marked as not created while still running.");
}
/// Quit the `Application`.View on GitHub (pinned to 0f8b1195e4)