{"record":{"id":"07e6af003ab96506","repo":"tauri-apps/tauri","slug":"state-not-managed-for-field-on-command","errorCode":null,"errorMessage":"state not managed for field `{}` on command `{}`. You must call `.manage()` before using this command","messagePattern":"state not managed for field `(.+?)` on command `(.+?)`\\. You must call `\\.manage\\(\\)` before using this command","errorType":"exception","errorClass":"InvokeError","httpStatus":null,"severity":"error","filePath":"crates/tauri/src/state.rs","lineNumber":63,"sourceCode":"}\n\nimpl<T: PartialEq> PartialEq for State<'_, T> {\n  fn eq(&self, other: &Self) -> bool {\n    self.0 == other.0\n  }\n}\n\nimpl<T: std::fmt::Debug> std::fmt::Debug for State<'_, T> {\n  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n    f.debug_tuple(\"State\").field(&self.0).finish()\n  }\n}\n\nimpl<'r, 'de: 'r, T: 'static, R: Runtime> CommandArg<'de, R> for State<'r, T> {\n  /// Grabs the [`State`] from the [`CommandItem`]. This will never fail.\n  fn from_command(command: CommandItem<'de, R>) -> Result<Self, InvokeError> {\n    command.message.state_ref().try_get().ok_or_else(|| {\n      InvokeError::from_anyhow(anyhow::anyhow!(\n        \"state not managed for field `{}` on command `{}`. You must call `.manage()` before using this command\",\n        command.key, command.name\n      ))\n    })\n  }\n}\n\n// Taken from: https://github.com/SergioBenitez/state/blob/556c1b94db8ce8427a0e72de7983ab5a9af4cc41/src/ident_hash.rs\n// This is a _super_ stupid hash. It just uses its input as the hash value. This\n// hash is meant to be used _only_ for \"prehashed\" values. In particular, we use\n// this so that hashing a TypeId is essentially a noop. This is because TypeIds\n// are already unique integers.\n#[derive(Default)]\nstruct IdentHash(u64);\n\nimpl std::hash::Hasher for IdentHash {\n  fn finish(&self) -> u64 {\n    self.0","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/tauri-apps/tauri/blob/2f1cd75b0f3fb72e6870d719bbfeadedcf8ca884/crates/tauri/src/state.rs#L45-L81","documentation":"Tauri commands can request managed state via a State<'_, T> parameter. CommandArg::from_command looks the value up by TypeId in the state container; if nothing of exactly that type was registered with Builder::manage/App::manage beforehand, try_get returns None and the command invocation is rejected with this error, naming the state field and the command.","triggerScenarios":"Invoking a command from the frontend (invoke('my_command')) whose signature includes a State<'_, T> parameter while the app never called .manage(...) for T; also when the managed type differs from the requested type (e.g. managed Mutex<Store> but requested State<Store>), or when the invoke races ahead of the manage() call in setup.","commonSituations":"Adding a State parameter to a command but forgetting .manage(); refactoring the type (wrapping in Mutex/RwLock, renaming) so TypeIds no longer match; invoking commands during window creation before setup managed the state.","solutions":["Register the state before the app runs: tauri::Builder::default().manage(MyState::new())...invoke_handler(...).run(...)","Make the managed type exactly match the command parameter, including Mutex<>/RwLock<> wrappers ('static, Send + Sync)","If timing is the issue, move manage() into Builder::setup (or onto the builder before run) so it always precedes the first invoke","For genuinely optional state, fetch with app.try_state::<T>() and handle None instead of failing"],"exampleFix":"// before: command needs State<AppStore> but nothing was managed\n#[tauri::command]\nfn items(state: State<AppStore>) -> Vec<Item> { state.all() }\n\n// after\nfn main() {\n  tauri::Builder::default()\n    .manage(AppStore::new())\n    .invoke_handler(tauri::generate_handler![items])\n    .run(tauri::generate_context!())\n    .unwrap();\n}","handlingStrategy":"validation","validationCode":null,"typeGuard":"// Rust: check state is managed before invoking command logic\nfn state_ready<T: Send + Sync + 'static>(app: &tauri::AppHandle) -> bool {\n  app.try_state::<T>().is_some()\n}","tryCatchPattern":"// frontend: distinguish the 'not managed' rejection from other command errors\ntry {\n  await invoke('get_items')\n} catch (e) {\n  if (String(e).includes('state not managed')) {\n    // initialization order bug: ensure .manage() runs before first invoke; surface a setup hint\n  } else throw e\n}","preventionTips":["Register all managed state in one place on the Builder (or first thing in setup) before invoke_handler runs","Keep a single source-of-truth list of managed types and review it when adding State parameters to commands","Match wrapper types exactly: manage(Mutex<T>::new(..)) pairs with State<Mutex<T>>, not State<T>","Write a startup smoke test that invokes each state-dependent command once"],"tags":["state","command","invoke","runtime","tauri"],"backgroundTag":null,"analyzedSha":"2f1cd75b0f3fb72e6870d719bbfeadedcf8ca884","analyzedAt":"2026-08-16T04:18:42.486Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}