tauri-apps/tauri · error

state() called before manage() for

Error message

state() called before manage() for {}

What it means

The `state<T>()` accessor on Manager/App/AppHandle/Window retrieves state previously registered with `manage::<T>()`. Tauri panics with the type name when no such state exists, because accessing unmanaged state is a programming error; `try_state` is the non-panicking alternative.

Solutions

  1. Call `app.manage(MyType::new(...))` in `Builder::setup` before any code accesses `state::<MyType>()`.
  2. Use `app.try_state::<T>()` and handle the None case gracefully instead of panicking.
  3. Ensure the exact type matches: `state::<Arc<Config>>()` vs `state::<Config>()` must match what was passed to manage().
  4. If state is produced asynchronously, block/gate access (e.g. Option in a Mutex managed upfront) rather than deferring manage().

Example fix

// before
#[tauri::command]
fn get_count(app: AppHandle) -> i32 { app.state::<Counter>().0 } // panics if never managed
// after
#[tauri::command]
fn get_count(app: AppHandle) -> i32 {
  app.try_state::<Counter>().map(|c| c.0).unwrap_or(0)
}
// and in setup:
.setup(|app| { app.manage(Counter(0)); Ok(()) })
Defensive patterns

Strategy: fallback

Validate before calling

if app.try_state::<Counter>().is_none() {
  app.manage(Counter(0));
}
let counter = app.state::<Counter>(); // safe now

Try / catch

// if using try_state in a command
let counter = app.try_state::<Counter>()
  .ok_or_else(|| tauri::Error::Anyhow(anyhow::anyhow!("state not initialized")))?;

Prevention

When it happens

Trigger: Calling `app.state::<T>()` (or handle/window.state) before `app.manage(T)` was called, or for a type that was never managed (different concrete type, e.g. managing `Config` but requesting `MyConfig`, or managing `Arc<Config>` vs `Config` mismatch).

Common situations: Accessing state from a command or event handler that runs before setup completes; a refactor renaming the state type; double-managed confusion where a wrapper type was stored instead of the inner type.

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/e931b1217b663e86. Report an issue: GitHub.

Appendix: source

Thrown at crates/tauri/src/lib.rs:734

  where
    T: Send + Sync + 'static,
  {
    // The caller decides to break the safety here, then OK, just let it go.
    unsafe { self.manager().state.unmanage() }
  }

  /// Retrieves the managed state for the type `T`.
  ///
  /// # Panics
  ///
  /// Panics if the state for the type `T` has not been previously [managed](Self::manage).
  /// Use [try_state](Self::try_state) for a non-panicking version.
  fn state<T>(&self) -> State<'_, T>
  where
    T: Send + Sync + 'static,
  {
    self.manager().state.try_get().unwrap_or_else(|| {
      panic!(
        "state() called before manage() for {}",
        std::any::type_name::<T>()
      )
    })
  }

  /// Attempts to retrieve the managed state for the type `T`.
  ///
  /// Returns `Some` if the state has previously been [managed](Self::manage). Otherwise returns `None`.
  fn try_state<T>(&self) -> Option<State<'_, T>>
  where
    T: Send + Sync + 'static,
  {
    self.manager().state.try_get()
  }

  /// Get a reference to the resources table of this manager.
  fn resources_table(&self) -> MutexGuard<'_, ResourceTable>;

View on GitHub (pinned to 460ec35447)