nautechsystems/nautilus_trader · error · anyhow::Error
Actor {actor_id} has not been registered with a Trader
Error message
Actor {actor_id} has not been registered with a Trader What it means
`reconnect_socket` sends a system command through the actor's registered system-command sender. This plumbing only exists once the actor is registered with a Trader; if `is_properly_registered()` is false, the call bails because it cannot route the reconnect command.
Source
Thrown at crates/common/src/actor/data_actor.rs:5753
.register_response_handler(command.request_id(), handler)?;
self.send_data_cmd(DataCommand::Request(command));
Ok(request_id)
}
/// Sends a fire-and-observe reconnect command.
///
/// # Errors
///
/// Returns an error if the actor is not registered, the endpoint label is invalid, the live
/// runner is unavailable, or the command channel is closed.
#[cfg(feature = "live")]
pub fn reconnect_socket(&self, client_id: ClientId, endpoint: &str) -> anyhow::Result<()> {
let endpoint = socket_endpoint(endpoint)?;
if !self.is_properly_registered() {
anyhow::bail!(
"Actor {} has not been registered with a Trader",
self.actor_id
);
}
let sender = try_get_system_command_sender()
.ok_or_else(|| anyhow::anyhow!("Live runner system command channel is unavailable"))?;
let trader_id = self
.trader_id
.ok_or_else(|| anyhow::anyhow!("Actor {} has no trader ID", self.actor_id))?;
let command = ReconnectSocket::new(trader_id, client_id, endpoint, self.timestamp_ns());
sender
.send(SystemCommand::ReconnectSocket(command))
.map_err(|_| anyhow::anyhow!("Live runner system command channel is closed"))?;
Ok(())
}
#[cfg(test)]View on GitHub (pinned to 18893faf8b)
Solutions
- Ensure the actor is registered with a Trader before reconnecting sockets
- Move reconnect logic into a post-registration lifecycle stage (e.g. on_start)
- Validate `is_properly_registered()` and defer/queue the reconnect until registration completes
Example fix
// before
actor.reconnect_socket(client_id, endpoint)?;
// after
if actor.is_properly_registered() {
actor.reconnect_socket(client_id, endpoint)?;
} else {
log::warn!("skipping reconnect: actor not registered");
} Defensive patterns
Strategy: validation
Validate before calling
if !actor.is_properly_registered() {
log::warn!("reconnect_socket deferred: actor not registered");
return Ok(());
} Try / catch
if let Err(e) = actor.reconnect_socket(client_id, &endpoint) {
if e.to_string().contains("not been registered") {
// queue reconnect for after registration
} else { return Err(e); }
} Prevention
- Only call live-only APIs from post-registration lifecycle hooks (on_start)
- Never invoke reconnect from constructors or pre-registration setup
- Check is_properly_registered before any system-command send
When it happens
Trigger: Calling `actor.reconnect_socket(client_id, endpoint)` on a DataActor before `register(trader_id, clock, cache)` completed; after registration was rolled back or in a standalone/unregistered actor context.
Common situations: Live trading setup where socket reconnect logic runs from a startup hook before trader registration; reusing an actor outside a Trader; reconnect triggered from a callback path when registration failed earlier.
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 {actor_id} already registered with trader {existin
- DataActor {actor_id} registration incomplete - validation fa
- Actor {actor_id} is already registered
- Python on_socket_state failed: {e}
- Failed to extract PyDataActor: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/1dc5859333d46605.
Report an issue: GitHub.