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_handle

View on GitHub (pinned to 52e4b6e71d)

Solutions

  1. 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.
  2. 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.
  3. Restructure so the lock is not held across fallible work: clone the Arc out of the table and drop the MutexGuard before propagating errors.
  4. 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

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


AI-assisted analysis of tauri-apps/tauri@52e4b6e71d (2026-08-20). Data as JSON: /api/errors/fa8c11fc349788a4. Report an issue: GitHub.