nautechsystems/nautilus_trader · error

Actor {actor_id} is already registered

Error message

Actor {actor_id} is already registered

What it means

The Python-registration path (add_actor_from_importable_config) creates the Python actor instance and then checks whether an actor with the same ActorId is already registered with the trader. Duplicate ActorIds are not allowed — the trader would otherwise own two components with the same identity — so it bails before adding. Registration must use unique actor IDs per trader.

Source

Thrown at crates/system/src/python/registration.rs:68

};

use crate::{registration::ensure_unique_order_id_tag, trader::Trader};

impl Trader {
    /// Adds an importable Python actor to the trader.
    ///
    /// # Errors
    ///
    /// Returns an error if the actor cannot be imported, configured, registered, or tracked.
    pub fn add_actor_from_importable_config(
        &mut self,
        config: &ImportableActorConfig,
    ) -> anyhow::Result<ActorId> {
        self.validate_actor_or_strategy_registration()?;

        let (python_actor, actor_id) = create_python_actor(config)?;
        if self.actor_ids.contains(&actor_id) {
            anyhow::bail!("Actor {actor_id} is already registered");
        }

        self.add_python_actor_instance(&python_actor, actor_id)?;

        log::info!(
            "Registered Python actor {actor_id} with trader {}",
            self.trader_id
        );
        Ok(actor_id)
    }

    /// Adds a constructed Python actor instance to the trader under `actor_id`.
    ///
    /// The actor must already be configured; this runs the registration sequence every Python
    /// actor needs and rolls back everything the attempt created if any step fails.
    ///
    /// # Errors
    ///

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ensure each actor config has a unique actor_id / instance_id override
  2. Check before adding whether the actor ID is already registered and skip or error in caller code
  3. Remove the duplicate registration attempt or de-duplicate config entries before applying
  4. If re-registering intentionally, remove the existing actor first

Example fix

// before
let id = create_python_actor(&config)?.1;
trader.add_actor_from_importable_config(&config)?; // bails if duplicate
// after
let id = create_python_actor(&config)?.1;
if !trader.actor_ids().contains(&id) {
    trader.add_actor_from_importable_config(&config)?;
}
Defensive patterns

Strategy: validation

Validate before calling

// Check for duplicate registration before adding
let actor_id = expected_actor_id(&config); // deterministic ID from config
anyhow::ensure!(
    !trader.actor_ids().contains(&actor_id),
    "actor {actor_id} already registered; skip or remove first"
);

Try / catch

match trader.add_actor_from_importable_config(&config) {
    Err(e) if e.to_string().contains("is already registered") => {
        log::debug!("actor already registered; skipping duplicate");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling add_actor_from_importable_config (or trader.add_actor with a Python actor) with a config whose factory/actor_id resolves to an ActorId already present in self.actor_ids — e.g. registering the same importable actor config twice.

Common situations: Applying a config twice (double registration on reconnect or restart); configs for multiple actors that produce identical IDs because their override/instance IDs collide; adding an actor to both the trader and another owner then retrying.

Related errors


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