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

  1. Ensure the actor is registered with a Trader before reconnecting sockets
  2. Move reconnect logic into a post-registration lifecycle stage (e.g. on_start)
  3. 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

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


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/1dc5859333d46605. Report an issue: GitHub.