nautechsystems/nautilus_trader · error

Actor {actor_id} is already registered

Error message

Actor {actor_id} is already registered

What it means

Trader.add_actor registers an actor component and first checks its ActorId against actor_ids already tracked. Registering an actor whose ID (name + instance_id) is already present is refused, since a trader cannot manage two components under one identity.

Source

Thrown at crates/system/src/trader.rs:310

    /// Adds an actor to the trader.
    ///
    /// # Errors
    ///
    /// Returns an error if:
    /// - The trader is not in a valid state for adding components.
    /// - An actor with the same ID is already registered.
    pub fn add_actor<T>(&mut self, actor: T) -> anyhow::Result<()>
    where
        T: DataActor + DataActorNative + Component + Debug + 'static,
    {
        self.validate_actor_or_strategy_registration()?;

        let actor_id = actor.actor_id();

        // Check for duplicate registration
        if self.actor_ids.contains(&actor_id) {
            anyhow::bail!("Actor {actor_id} is already registered");
        }

        let component_id = ComponentId::from(actor_id);
        let clock = self.create_component_clock(component_id);

        let mut actor_mut = actor;
        actor_mut.register(self.trader_id, clock, self.cache.clone())?;

        self.add_registered_actor(actor_mut)
    }

    /// Adds an actor to the trader using a factory function.
    ///
    /// The factory function is called at registration time to create the actor,
    /// avoiding cloning issues with non-cloneable actor types.
    ///
    /// # Errors
    ///

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Give each actor a unique name or instance_id when constructing it.
  2. Guard add_actor with a check of existing actor ids.
  3. Rebuild the trader/system instead of re-adding the same component.

Example fix

// before
trader.add_actor(MyActor())
trader.add_actor(MyActor())  # same default name -> duplicate id
// after
trader.add_actor(MyActor(name="Actor-001"))
trader.add_actor(MyActor(name="Actor-002"))
Defensive patterns

Strategy: validation

Validate before calling

existing = {a.actor_id for a in trader.actors()}
assert actor.actor_id() not in existing, f"{actor.actor_id()} already registered"

Type guard

def actor_is_new(actor, trader) -> bool:
    return actor.actor_id() not in {a.actor_id() for a in trader.actors()}

Try / catch

match trader.add_actor(actor) {
    Err(e) if e.to_string().contains("is already registered") => {
        log::warn!("actor already present; skipping");
    }
    r => r?,
}

Prevention

When it happens

Trigger: Calling trader.add_actor twice with the same actor instance or two actors built with identical names/instance ids; also re-adding an actor after it was only ID-tracked via add_actor_id_for_lifecycle.

Common situations: Re-running setup code in notebooks/tests, constructing actors without distinct `name` or `instance_id` args, retry logic that re-adds the same component after a partial failure.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


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