nautechsystems/nautilus_trader · error
DataActor must be registered before accessing clock
Error message
DataActor must be registered before accessing clock
What it means
DataActor::clock_rc returns a clone of the actor's Rc<RefCell<dyn Clock>>, which is populated only during registration with a Trader/Node. If called before registration, the Option is None and this panic fires. It exists to give callers a cheap clock handle while enforcing that the actor is only used after being registered.
Source
Thrown at crates/common/src/actor/data_actor.rs:206
.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()
}
/// Returns a read-only cache borrow.
///
/// # Panics
///
/// Panics if the actor has not yet been registered.
fn cache_ref(&self) -> Ref<'_, Cache> {
self.core()
.cache
.as_ref()
.expect("DataActor must be registered before accessing cache")
.borrow()
}
/// Returns a clone of the reference-counted cache.
///View on GitHub (pinned to 18893faf8b)
Solutions
- Move clock/timer usage into on_start (or later lifecycle callbacks), which run only after registration
- Register the actor (trader.add_actor / node registration) before calling any clock-dependent method
- If a clock handle is needed pre-registration, pass one explicitly into the actor's constructor rather than using clock_rc()
Example fix
// before
impl DataActor for MyActor {
fn new(&mut self) { self.clock_rc(); } // panics: not registered yet
}
// after
impl DataActor for MyActor {
fn on_start(&mut self) {
self.clock_rc(); // safe: registered before on_start runs
}
} Defensive patterns
Strategy: validation
Validate before calling
fn actor_is_registered(actor_is_registered_flag: bool) {
assert!(actor_is_registered_flag, "register actor before using clock APIs");
} Try / catch
// Rust panics are not catchable in normal code; guard via lifecycle ordering:
fn on_start(&mut self) {
// guaranteed registered here
let clock = self.clock_rc();
} Prevention
- Use clock APIs only inside on_start and later lifecycle callbacks
- Never touch clock_rc in constructors or before trader.add_actor
- In tests, register actors through the standard harness before exercising handlers
When it happens
Trigger: Calling clock_rc() (directly or via any actor method that needs the clock, e.g. scheduling timers via request or emitting log timestamps) before the actor has been registered — e.g. in the actor's constructor, in new(), or before trader.add_actor / node registration completes.
Common situations: Starting timers or touching clock-dependent APIs in custom actor initialization instead of in on_start; registering the actor with a kernel but invoking handler code immediately in the same thread before registration finishes; tests constructing a DataActor standalone and calling clock-backed methods.
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 calling `clock_mut()`
- 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/cd718b5b3a606a6b.
Report an issue: GitHub.