{"record":{"id":"4a84a54c8c2ffb84","repo":"nautechsystems/nautilus_trader","slug":"dataactor-must-be-registered-before-calling-ca","errorCode":null,"errorMessage":"DataActor {} must be registered before calling `cache()` - trader_id: {:?}","messagePattern":"DataActor (.+?) must be registered before calling `cache\\(\\)` - trader_id: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/common/src/actor/data_actor.rs","lineNumber":4108,"sourceCode":"        });\n        ClockApi::new(clock.as_ref())\n    }\n\n    fn clock_ref(&self) -> Ref<'_, dyn Clock> {\n        self.clock\n            .as_ref()\n            .unwrap_or_else(|| {\n                panic!(\n                    \"DataActor {} must be registered before calling `clock_ref()` - trader_id: {:?}\",\n                    self.actor_id, self.trader_id\n                )\n            })\n            .borrow()\n    }\n\n    fn cache_api(&self) -> CacheApi<'_> {\n        let cache = self.cache.as_ref().unwrap_or_else(|| {\n            panic!(\n                \"DataActor {} must be registered before calling `cache()` - trader_id: {:?}\",\n                self.actor_id, self.trader_id\n            )\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>>,","sourceCodeStart":4090,"sourceCodeEnd":4126,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/common/src/actor/data_actor.rs#L4090-L4126","documentation":"`DataActor::cache_api()` panics when the actor's cache handle is `None`, i.e. the actor was not registered with a trader that injects the cache. Any cache access on an unregistered actor violates the lifecycle contract and panics.","triggerScenarios":"Calling `cache_api()`/cache accessors (e.g. `cache_order`, instrument lookups) before the actor is registered with a trader.","commonSituations":"Querying the cache in the actor constructor or before `on_start`; standalone actors in tests without registration; actors added to a node but accessed from another thread/context before registration completes.","solutions":["Register the actor with a trader/node so the cache is injected.","Move cache access into `on_start` or event handlers that run post-registration.","If the actor needs cache data at construction, pass it explicitly instead of reading the injected cache."],"exampleFix":"// before\nlet actor = MyActor::new();\nlet order = actor.cache_api().order(&client_order_id); // panic\n// after\nimpl DataActor for MyActor {\n    fn on_start(&mut self) {\n        let order = self.cache_api().order(&self.client_order_id);\n    }\n}","handlingStrategy":"type-guard","validationCode":"if actor.is_registered() {\n    let order = actor.cache_api().order(&client_order_id);\n}","typeGuard":"fn cache_available(actor: &DataActor) -> bool { actor.is_registered() }","tryCatchPattern":null,"preventionTips":["Access the cache only inside on_start/handler methods","Pass construction-time data explicitly rather than reading the injected cache early","In tests, register actors with a stub trader/cache before calling cache accessors"],"tags":["actor","lifecycle","cache","rust"],"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"}