{"record":{"id":"ec169c7c624764f2","repo":"nautechsystems/nautilus_trader","slug":"dataactor-actor-id-already-registered-with-trade","errorCode":null,"errorMessage":"DataActor {actor_id} already registered with trader {existing_trader_id}","messagePattern":"DataActor (.+?) already registered with trader (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/common/src/actor/data_actor.rs","lineNumber":4129,"sourceCode":"            )\n        });\n        CacheApi::new(cache.as_ref())\n    }\n\n    /// Register the data actor with a trader.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if the actor has already been registered with a trader\n    /// or if the provided dependencies are invalid.\n    pub fn register(\n        &mut self,\n        trader_id: TraderId,\n        clock: Rc<RefCell<dyn Clock>>,\n        cache: Rc<RefCell<Cache>>,\n    ) -> anyhow::Result<()> {\n        if let Some(existing_trader_id) = self.trader_id {\n            anyhow::bail!(\n                \"DataActor {} already registered with trader {existing_trader_id}\",\n                self.actor_id\n            );\n        }\n\n        // Validate clock by attempting to access it\n        {\n            let _timestamp = clock.borrow().timestamp_ns();\n        }\n\n        // Validate cache by attempting to access it\n        {\n            let _cache_borrow = cache.borrow();\n        }\n\n        self.trader_id = Some(trader_id);\n        self.clock = Some(clock);\n        self.cache = Some(cache);","sourceCodeStart":4111,"sourceCodeEnd":4147,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/common/src/actor/data_actor.rs#L4111-L4147","documentation":"`DataActor::register` refuses to run twice. If the actor already holds a `trader_id`, calling registration again would silently re-bind the actor to another trader; the library bails instead, preserving a one-to-one actor/trader relationship for the actor's lifetime.","triggerScenarios":"Calling `register(trader_id, clock, cache)` on a DataActor that was previously registered; reusing one actor instance across two traders or a trader restart without constructing a new actor.","commonSituations":"Building a second strategy/trader in the same process and accidentally sharing an actor; retrying registration after a failure; running a backtest twice with cached actor instances.","solutions":["Create a new DataActor instance for the new registration","Ensure each actor is registered exactly once per trader lifecycle","If re-registering after a partial failure is intended, reset/rebuild the actor instead of reusing it"],"exampleFix":"// before\nactor.register(trader_id_a.clone(), ...);\nactor.register(trader_id_b.clone(), ...); // bails\n// after\nlet actor_a = MyActor::new();\nlet actor_b = MyActor::new();\nactor_a.register(trader_id_a, ...);\nactor_b.register(trader_id_b, ...);","handlingStrategy":"validation","validationCode":"if actor_is_registered(&actor) {\n    return Err(anyhow::anyhow!(\"actor already registered; create a new instance\"));\n}","typeGuard":"fn is_unregistered(actor: &DataActor) -> bool {\n    actor.trader_id().is_none()\n}","tryCatchPattern":"if let Err(e) = actor.register(trader_id, clock.clone(), cache.clone()) {\n    log::warn!(\"registration skipped: {e}\"); // treat double-registration as idempotent no-op if safe\n}","preventionTips":["Register each actor exactly once per lifecycle","Never share actor instances between traders","Rebuild actors on trader restart instead of reusing them"],"tags":["actor","registration","state"],"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"}