nautechsystems/nautilus_trader · error
DataActor {} must be registered before calling `clock_mut()`
Error message
DataActor {} must be registered before calling `clock_mut()` - trader_id: {:?} What it means
`DataActor::clock_mut()` panics when the actor's internal clock handle is `None`, which happens only if the actor has not been registered with a trader (registration injects the clock, cache, and other context). This is a lifecycle misuse: the accessor is being called outside the registered lifetime.
Source
Thrown at crates/common/src/actor/data_actor.rs:189
/// references do not cross those boundaries.
pub trait DataActorNative {
/// Returns the actor core.
fn core(&self) -> &DataActorCore;
/// Returns the mutable actor core.
fn core_mut(&mut self) -> &mut DataActorCore;
/// Returns the mutable clock borrow for the actor.
///
/// # Panics
///
/// Panics if the actor has not been registered with a trader.
fn clock_mut(&mut self) -> RefMut<'_, dyn Clock> {
let core = self.core_mut();
core.clock
.as_ref()
.unwrap_or_else(|| {
panic!(
"DataActor {} must be registered before calling `clock_mut()` - trader_id: {:?}",
core.actor_id, core.trader_id
)
})
.borrow_mut()
}
/// Returns a clone of the reference-counted clock.
///
/// # Panics
///
/// Panics if the actor has not yet been registered.
fn clock_rc(&self) -> Rc<RefCell<dyn Clock>> {
self.core()
.clock
.as_ref()
.expect("DataActor must be registered before accessing clock")
.clone()View on GitHub (pinned to 18893faf8b)
Solutions
- Register the actor with a trader (or run it through a node/kernel) before calling `clock_mut()`.
- Move clock-dependent logic into `on_start`/other post-registration hooks.
- In tests, use the registered harness (e.g. `TestComponentStubs`/register helpers) instead of raw actors.
Example fix
// before
impl Actor for MyActor {
fn new(...) -> Self {
let t = self.clock_mut().timestamp_ns(); // panic
}
}
// after
impl Actor for MyActor {
fn on_start(&mut self) {
let t = self.clock_mut().timestamp_ns(); // clock injected at registration
}
} Defensive patterns
Strategy: type-guard
Validate before calling
// guard before access
fn clock_ready(actor: &DataActor) -> bool { actor.is_registered() } Type guard
fn clock_ready(actor: &DataActor) -> bool {
actor.is_registered() // only true after trader registration injects the clock
} Try / catch
// Rust panics are not catchable in safe code; assert the precondition instead debug_assert!(actor.is_registered(), "call clock_mut() only after trader registration");
Prevention
- Never call clock/cache accessors in constructors or before on_start
- Run actors through Trader/node registration even in tests
- Keep lifecycle-dependent logic inside lifecycle hook methods
When it happens
Trigger: Calling `clock_mut()` in the actor's constructor or `on_start` before registration, or calling it manually on a standalone `DataActor` never passed to a `Trader`/node.
Common situations: Using an actor outside a running trader in tests; doing clock-dependent setup in the constructor instead of lifecycle hooks; creating actors and calling accessors before `trader.add_actor(...)`.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- DataActor must be registered before accessing clock
- DataActor must be registered before accessing cache
- DataActor {} must be registered before calling `clock()` - t
- DataActor {} must be registered before calling `clock_ref()`
- DataActor {} must be registered before calling `cache()` - t
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/e15001d6ae4d8d5b.
Report an issue: GitHub.