{"record":{"id":"1a0fbca8eb2273c8","repo":"nautechsystems/nautilus_trader","slug":"dataactor-must-be-registered-before-calling-cl-1a0fbc","errorCode":null,"errorMessage":"DataActor {} must be registered before calling `clock()` - trader_id: {:?}","messagePattern":"DataActor (.+?) must be registered before calling `clock\\(\\)` - trader_id: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/common/src/actor/data_actor.rs","lineNumber":4086,"sourceCode":"    }\n\n    /// Returns the actors ID.\n    pub fn actor_id(&self) -> ActorId {\n        self.actor_id\n    }\n\n    fn default_actor_id() -> ActorId {\n        ActorId::from(stringify!(DataActor))\n    }\n\n    /// Returns a UNIX nanoseconds timestamp from the actor's internal clock.\n    pub fn timestamp_ns(&self) -> UnixNanos {\n        self.clock_ref().timestamp_ns()\n    }\n\n    pub(super) fn clock_api(&self) -> ClockApi<'_> {\n        let clock = self.clock.as_ref().unwrap_or_else(|| {\n            panic!(\n                \"DataActor {} must be registered before calling `clock()` - trader_id: {:?}\",\n                self.actor_id, self.trader_id\n            )\n        });\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    }","sourceCodeStart":4068,"sourceCodeEnd":4104,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/common/src/actor/data_actor.rs#L4068-L4104","documentation":"`DataActor::clock_api()` panics if the actor's clock handle is `None`, i.e. the actor has not been registered with a trader that injects the clock. Accessing clock-based APIs like `timestamp_ns()` on an unregistered actor is invalid lifecycle usage.","triggerScenarios":"Calling `timestamp_ns()`/`clock_api()` (which routes through the clock) before the actor is registered with a trader.","commonSituations":"Standalone actors used without a trader; clock access during construction or before `on_start`; test harnesses that instantiate `DataActor` without registering it.","solutions":["Register the actor with a trader/node so the clock is injected.","Defer time-dependent calls to `on_start` or later lifecycle hooks.","For test scenarios, register the actor with a test clock rather than calling accessors on an unregistered actor."],"exampleFix":"// before\nlet mut actor = MyActor::new();\nlet ts = actor.timestamp_ns(); // panic: not registered\n// after\nlet mut actor = MyActor::new();\ntrader.add_actor(actor);\n// within on_start: self.timestamp_ns() is valid","handlingStrategy":"type-guard","validationCode":"if !actor.is_registered() {\n    eprintln!(\"timestamp_ns() requires a registered actor\");\n    return;\n}","typeGuard":"fn has_clock(actor: &DataActor) -> bool { actor.is_registered() }","tryCatchPattern":null,"preventionTips":["Gate all time queries behind on_start or later hooks","Register actors before manually invoking their accessors in tests","Never cache clock references across registration boundaries"],"tags":["actor","lifecycle","clock","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-14T00:17:10.932Z"}