{"record":{"id":"f18d1faabec21dfd","repo":"nautechsystems/nautilus_trader","slug":"component-id-is-already-mutably-borrowed-this","errorCode":null,"errorMessage":"Component '{id}' is already mutably borrowed. This would create aliasing mutable references (undefined behavior).","messagePattern":"Component '(.+?)' is already mutably borrowed\\. This would create aliasing mutable references \\(undefined behavior\\)\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/common/src/component.rs","lineNumber":554,"sourceCode":"\n    component_ref\n}\n\n/// Safely calls `start()` on a component in the global registry.\n///\n/// # Errors\n///\n/// - Returns an error if the component is not found.\n/// - Returns an error if the component is already borrowed.\n/// - Returns an error if `start()` fails.\npub fn start_component(id: &Ustr) -> anyhow::Result<()> {\n    let component_ref = with_component_registry(|registry| {\n        let component_ref = registry\n            .get(id)\n            .ok_or_else(|| anyhow::anyhow!(\"Component '{id}' not found in global registry\"))?;\n\n        if !registry.try_borrow(*id) {\n            anyhow::bail!(\n                \"Component '{id}' is already mutably borrowed. \\\n                 This would create aliasing mutable references (undefined behavior).\"\n            );\n        }\n\n        Ok::<_, anyhow::Error>(component_ref)\n    })?;\n\n    let _guard = BorrowGuard::new(*id);\n\n    // SAFETY: Borrow tracking ensures exclusive access\n    unsafe {\n        let component = &mut *component_ref.get();\n        component.start()\n    }\n}\n\n/// Returns the state of a component in the global registry.","sourceCodeStart":536,"sourceCodeEnd":572,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/common/src/component.rs#L536-L572","documentation":"The global component registry enforces single mutable borrow of each registered component via a try_borrow flag. start_component first try_borrows the component; if it is already mutably borrowed (another lifecycle call in progress), it rejects with this message to prevent aliasing &mut references, which would be undefined behavior in Rust.","triggerScenarios":"Calling start_component for a component id while another lifecycle operation (start/stop/reset/dispose or component_state access that is still in scope) holds the borrow — e.g. calling start from inside the component's own start() callback, or concurrent start_component calls for the same id.","commonSituations":"Re-entrant lifecycle calls: a component's on_start handler calling start_component on itself; background threads triggering start while the main loop already borrowed it; nested strategies starting their parent; deadlock-avoidance tests.","solutions":["Never call start_component (or other lifecycle functions) on a component from within that component's own callbacks.","Ensure the borrow is released before the next call: lifecycle helpers release on scope exit and on panic; check that no closure still holds the returned reference.","Serialize lifecycle operations per component with your own lock/queue so only one runs at a time.","Restructure so the component signals completion (e.g. via message/event) and the caller starts it afterwards, instead of nested calls."],"exampleFix":"// before\nfn on_start(&mut self) {\n    start_component(&self.id()); // self is already borrowed -> UB guard fires\n}\n// after\nfn on_start(&mut self) {\n    // schedule external start instead of borrowing self\n    self.msgbus.publish_start_request(&self.id());\n}","handlingStrategy":"try-catch","validationCode":"fn is_lifecycle_idle(component_id: &ComponentId) -> bool {\n    // ensure no lifecycle task is in flight for this id before starting\n    LIFECYCLE_IN_FLIGHT.get(component_id).map_or(true, |b| !*b)\n}","typeGuard":null,"tryCatchPattern":"match start_component(id) {\n    Err(e) if e.to_string().contains(\"already mutably borrowed\") => {\n        log::warn!(\"component {id} busy; retrying after in-flight op\");\n    }\n    other => other?,\n}","preventionTips":["Never start a component from inside its own callbacks (no re-entrancy)","Serialize lifecycle calls per component id","Do not hold the returned &mut across other registry calls","Release borrows promptly; scope the reference tightly"],"tags":["borrow-checker","component","lifecycle","aliasing","undefined-behavior"],"backgroundTag":"invalid-state-transition","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}