{"record":{"id":"c2c63f81f62c7c5e","repo":"DioxusLabs/dioxus","slug":"the-hook-list-is-already-borrowed-this-error-is-l","errorCode":null,"errorMessage":"The hook list is already borrowed: This error is likely caused by trying to use  hook inside a hook which violates the rules of hooks.","messagePattern":"The hook list is already borrowed: This error is likely caused by trying to use  hook inside a hook which violates the rules of hooks\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/scope_context.rs","lineNumber":343,"sourceCode":"    /// Queue an effect to run after the next render\n    pub(crate) fn queue_effect(&self, f: impl FnOnce() + 'static) {\n        Runtime::with(|rt| rt.queue_effect(self.id, f));\n    }\n\n    /// Store a value in the hook list, returning the value.\n    pub(crate) fn use_hook<State: Clone + 'static>(\n        &self,\n        initializer: impl FnOnce() -> State,\n    ) -> State {\n        let cur_hook = self.hook_index.get();\n\n        // The hook list works by keeping track of the current hook index and pushing the index forward\n        // while retrieving the hook value.\n        self.hook_index.set(cur_hook + 1);\n\n        let mut hooks = self.hooks\n            .try_borrow_mut()\n            .expect(\"The hook list is already borrowed: This error is likely caused by trying to use  hook inside a hook which violates the rules of hooks.\");\n\n        // Try and retrieve the hook value if it exists\n        if let Some(existing) = self.use_hook_inner::<State>(&mut hooks, cur_hook) {\n            return existing;\n        }\n\n        // Otherwise, initialize the hook value. In debug mode, we allow hook types to change after a hot patch\n        self.push_hook_value(&mut hooks, cur_hook, initializer())\n    }\n\n    // The interior version that gets monomorphized by the `State` type but not the `initializer` type.\n    // This helps trim down binary sizes\n    fn use_hook_inner<State: Clone + 'static>(\n        &self,\n        hooks: &mut Vec<Box<dyn std::any::Any>>,\n        cur_hook: usize,\n    ) -> Option<State> {\n        hooks.get(cur_hook).and_then(|inn| {","sourceCodeStart":325,"sourceCodeEnd":361,"githubUrl":"https://github.com/DioxusLabs/dioxus/blob/393d190a801ccb441d41923e232289b4f8a5c669/packages/core/src/scope_context.rs#L325-L361","documentation":"Each scope's hooks live in a RefCell list that use_hook borrows mutably. This panic fires when try_borrow_mut fails, i.e. a hook is requested while the hook list is already borrowed. In practice this is a re-entrant hook call: another hook is invoked inside the initializer closure passed to use_hook (or a similar hook-creating closure) while the outer use_hook still holds the borrow, violating the rules of hooks.","triggerScenarios":"Writing a custom hook as use_hook(|| { use_signal(|| 0) ... }) so the inner hook call runs inside the outer hook's borrow; calling any dioxus hook (use_signal, use_state, use_resource, use_effect...) inside the initializer or cleanup closure of another hook; custom hooks that invoke hook-creating helpers from within a closure.","commonSituations":"Refactoring a component into a custom hook and leaving hook calls inside a closure; wrapping hook initialization in helper closures or factories; copy-pasting hook bodies into use_hook initializers.","solutions":["Move nested hook calls to the top level of the custom hook function, then pass the results into use_hook","Never call other hooks inside a use_hook initializer/cleanup; hoist them out","Write custom hooks as plain functions that call other hooks directly: fn use_thing() { let s = use_signal(..); ... }","Audit every closure in the failing hook for hidden dioxus::prelude hook calls"],"exampleFix":"// before\nfn use_counter() -> Signal<i32> {\n    use_hook(|| {\n        let count = use_signal(|| 0); // panics: hook inside hook borrow\n        count\n    })\n}\n// after\nfn use_counter() -> Signal<i32> {\n    use_signal(|| 0) // hooks only at the top level of the custom hook\n}","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only call hooks at the top level of components or custom hook functions — never inside closures passed to other hooks","Write custom hooks as plain functions calling other hooks directly, not as use_hook wrappers","Grep custom hooks for `use_` calls nested inside move || closures during code review","Keep hook ordering unconditional, mirroring React's rules of hooks"],"tags":["hooks","core","rules-of-hooks","borrow","panic"],"backgroundTag":null,"analyzedSha":"393d190a801ccb441d41923e232289b4f8a5c669","analyzedAt":"2026-08-16T11:27:45.815Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}