tauri-apps/tauri · error
poisoned window resources table
Error message
poisoned window resources table
What it means
Webview implements the Manager trait's resources_table() by locking a std::sync::Mutex around the ResourceTable that tracks Tauri resources (named streams/buffers used by core and plugins such as fs and http). Rust marks a mutex 'poisoned' when any thread panics while holding it, and every later lock fails; Tauri turns that failure into .expect("poisoned window resources table"), so this panic is the symptom of an EARLIER panic, not the root cause. Once poisoned, every subsequent resources_table() call on this Webview panics for the lifetime of the process.
Source
Thrown at crates/tauri/src/webview/mod.rs:2427
Ok(())
});
```
"####
)]
fn unlisten(&self, id: EventId) {
self.manager.unlisten(id)
}
}
impl<R: Runtime> Emitter<R> for Webview<R> {}
impl<R: Runtime> Manager<R> for Webview<R> {
fn resources_table(&self) -> MutexGuard<'_, ResourceTable> {
self
.resources_table
.lock()
.expect("poisoned window resources table")
}
}
impl<R: Runtime> ManagerBase<R> for Webview<R> {
fn manager(&self) -> &AppManager<R> {
&self.manager
}
fn manager_owned(&self) -> Arc<AppManager<R>> {
self.manager.clone()
}
fn runtime(&self) -> RuntimeOrDispatch<'_, R> {
self.app_handle.runtime()
}
fn managed_app_handle(&self) -> &AppHandle<R> {
&self.app_handleView on GitHub (pinned to 52e4b6e71d)
Solutions
- Reproduce with RUST_BACKTRACE=1 and find the FIRST panic in the logs — that panic poisoned the mutex; this expect is only the second failure.
- Audit every Resource::drop and every code path that holds the resources_table() guard for unwrap/expect/indexing that can panic, and make them log errors instead.
- Restructure so the lock is not held across fallible work: clone the Arc out of the table and drop the MutexGuard before propagating errors.
- Restart the application (or re-create the Webview) after fixing — a poisoned mutex cannot be un-poisoned in-process.
Example fix
// before: panicking Drop runs while the resources-table lock is held,
// poisoning the mutex for every later resources_table() call
impl Resource for MyStream {
fn drop(&mut self) {
let mut buf = [0u8; 8];
self.file.read_exact(&mut buf).expect("final read failed");
}
}
// after: never panic inside Drop — log instead
impl Resource for MyStream {
fn drop(&mut self) {
let mut buf = [0u8; 8];
if let Err(e) = self.file.read_exact(&mut buf) {
log::error!("MyStream final read failed: {e}");
}
}
} Defensive patterns
Strategy: try-catch
Try / catch
use std::panic::{catch_unwind, AssertUnwindSafe};
// resources_table() panics when the underlying mutex is poisoned;
// contain it instead of crashing the calling thread
match catch_unwind(AssertUnwindSafe(|| window.resources_table())) {
Ok(table) => { /* use the ResourceTable guard here */ }
Err(_) => {
log::error!("Webview resource table poisoned — re-create the webview");
// e.g. rebuild the webview or signal the user to restart
}
} Prevention
- Never panic in Resource::drop implementations — drops run while the table lock is held and poison it.
- Install a panic hook (std::panic::set_hook) at startup that logs payload + backtrace, so the ORIGINAL poisoning panic is visible; this expect is only the second failure.
- Keep resources_table() guard scopes minimal: clone the Arc out of the table and drop the guard before any fallible work.
- Replace unwrap/expect with Result handling in commands and plugin code that touch resources by rid.
When it happens
Trigger: Any panic that occurs while a thread holds this Webview's resources-table mutex, followed by any later access. Typical poisoners: a panicking Resource::drop implementation (the table destroys resources while its lock is held), a panic in plugin code registering or resolving resources (tauri-plugin-fs streams, http bodies), or a command that panics while a MutexGuard from resources_table() is alive. The visible panic then fires on the next resource operation, e.g. an invoke whose command resolves a resource by rid.
Common situations: Custom Resource implementations using unwrap/expect/indexing in Drop; long-lived apps streaming files where a mid-stream panic occurs and every later IPC touching resources crashes; upgrades of tauri or resource-using plugins that changed drop order; panics inside commands that iterate the resource table.
Related errors
- poisoned window resources table
- poisoned window resources table
- poisoned window
- failed to read resource file name
- failed to read resource folder name
AI-assisted analysis of tauri-apps/tauri@52e4b6e71d (2026-08-20).
Data as JSON: /api/errors/fa8c11fc349788a4.
Report an issue: GitHub.