tauri-apps/tauri · critical

state not found for type

Error message

state not found for type {}

What it means

State<'_, T>::get retrieves managed state of type T registered via Manager::manage. If no state of that type was ever managed on the app, try_get returns None and get panics with the type name. It is an unrecoverable programmer error: state must be registered before the app runs the event loop.

Solutions

  1. Register the state before running: app.manage(MyState::default())
  2. Use try_get::<T>() to handle absence gracefully instead of panicking
  3. Verify the exact type T matches the one passed to manage (generics are compared by TypeId)

Example fix

// before
let state = app.state::<Db>();
// after
fn main() -> tauri::Result<()> {
  tauri::Builder::default()
    .setup(|app| { app.manage(Db::connect()?); Ok(()) })
    .run(tauri::generate_context!())
}
Defensive patterns

Strategy: validation

Validate before calling

if app.try_state::<MyState>().is_none() {
  eprintln!("MyState not managed; call app.manage(MyState::default()) before run");
}

Type guard

fn has_state<T: Send + Sync + 'static>(app: &tauri::AppHandle) -> bool {
  app.try_state::<T>().is_some()
}

Try / catch

std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| app.state::<MyState>()))
  .map_err(|_| anyhow::anyhow!("state <MyState> not managed"))

Prevention

When it happens

Trigger: Calling app.state::<MyState>() or window.state::<T>() when Manager::manage(MyState) / manage was never called, or called after .run() started, or on a different T than what was managed.

Common situations: Forgetting to call .manage(MyState::default()) in setup or before run; managing a different generic instantiation (e.g. HashMap<String, i32> vs HashMap<i32, i32>); accessing state in a plugin before it is initialized; tests spawning the app without setup.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of tauri-apps/tauri@460ec35447 (2026-09-18). Data as JSON: /api/errors/f14f2178b66059fe. Report an issue: GitHub.

Appendix: source

Thrown at crates/tauri/src/state.rs:145

  }

  /// SAFETY: Calling this method will move the `value`,
  /// which will cause references obtained through [Self::try_get] to dangle.
  pub(crate) unsafe fn unmanage<T: Send + Sync + 'static>(&self) -> Option<T> {
    let mut map = self.map.lock().unwrap();
    let type_id = TypeId::of::<T>();
    let state = map.remove(&type_id)?;
    let value = state
      .downcast::<T>()
      .expect("the type of the key should be same as the type of the value");
    Some(*value)
  }

  /// Gets the state associated with the specified type.
  pub fn get<T: 'static>(&self) -> State<'_, T> {
    self
      .try_get()
      .unwrap_or_else(|| panic!("state not found for type {}", std::any::type_name::<T>()))
  }

  /// Gets the state associated with the specified type.
  pub fn try_get<T: 'static>(&self) -> Option<State<'_, T>> {
    let map = self.map.lock().unwrap();
    let type_id = TypeId::of::<T>();
    let state = map.get(&type_id)?;
    let value = state
      .downcast_ref::<T>()
      .expect("the type of the key should be same as the type of the value");
    // SAFETY: We ensure the lifetime of `value` is the same as [StateManager] and `value` will not be mutated/moved.
    let v_ref = unsafe { &*(value as *const T) };
    Some(State(v_ref))
  }
}

// Ported from https://github.com/SergioBenitez/state/blob/556c1b94db8ce8427a0e72de7983ab5a9af4cc41/tests/main.rs
#[cfg(test)]

View on GitHub (pinned to 460ec35447)