nautechsystems/nautilus_trader · error
Actor '{actor_id}' is already tracked by trader
Error message
Actor '{actor_id}' is already tracked by trader What it means
add_actor_id_for_lifecycle registers just an ActorId (for a native DataActor type) with the trader for lifecycle management. If the ID is already in actor_ids the call bails, since two lifecycle-tracked components cannot share one ID.
Source
Thrown at crates/system/src/trader.rs:387
Ok(())
}
/// Adds an actor ID to the trader's lifecycle management without consuming the actor.
///
/// This is useful when the actor is already registered in the global component registry
/// but the trader needs to track it for lifecycle management. The caller is responsible
/// for ensuring the actor is properly registered in the global registries.
///
/// # Errors
///
/// Returns an error if the actor ID is already tracked by this trader.
pub fn add_actor_id_for_lifecycle<T>(&mut self, actor_id: ActorId) -> anyhow::Result<()>
where
T: DataActor + DataActorNative + Debug + 'static,
{
// Check for duplicate registration
if self.actor_ids.contains(&actor_id) {
anyhow::bail!("Actor '{actor_id}' is already tracked by trader");
}
// Store actor ID for lifecycle management
self.actor_ids.push(actor_id);
self.actor_state_callbacks.insert(
actor_id,
ComponentStateCallbacks {
load: Self::load_component_state::<T>,
save: Self::save_component_state::<T>,
},
);
log::debug!(
"Added actor ID '{actor_id}' to trader {} for lifecycle management",
self.trader_id
);
Ok(())View on GitHub (pinned to 18893faf8b)
Solutions
- Register each actor ID exactly once per trader.
- Don't mix add_actor and add_actor_id_for_lifecycle for the same ID.
- Create a fresh Trader per run/test instead of reusing a populated one.
Example fix
// before
trader.add_actor_id_for_lifecycle::<MyActor>(actor_id)?;
trader.add_actor_id_for_lifecycle::<MyActor>(actor_id)?; // duplicate
// after
if !trader.actor_ids.contains(&actor_id) {
trader.add_actor_id_for_lifecycle::<MyActor>(actor_id)?;
} Defensive patterns
Strategy: validation
Validate before calling
if trader.actor_ids().contains(&actor_id) {
return Ok(()); // or skip
}
trader.add_actor_id_for_lifecycle::<T>(actor_id)?; Type guard
fn lifecycle_id_registered(trader: &Trader, id: &ActorId) -> bool {
trader.actor_ids().contains(id)
} Try / catch
match trader.add_actor_id_for_lifecycle::<T>(actor_id) {
Err(e) if e.to_string().contains("already tracked by trader") => Ok(()),
other => other,
} Prevention
- Register each actor ID through exactly one path (add_actor OR id-for-lifecycle)
- Check actor_ids before adding lifecycle-only registrations
- Avoid re-running registration setup on the same trader instance
When it happens
Trigger: Calling the public add_actor_id_for_lifecycle twice with the same ActorId, or after that ID was already registered through add_actor (which also pushes into actor_ids).
Common situations: Double registration during node/kernel setup, registering the same actor both as a full component and as an ID for lifecycle, test code re-invoking setup per case without a fresh trader.
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
- Actor {actor_id} is already registered
- Execution algorithm '{exec_algorithm_id}' is already tracked
- DataActor {} must be registered before calling `clock_mut()`
- DataActor {} must be registered before calling `clock()` - t
- DataActor {} must be registered before calling `clock_ref()`
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/00099068c354a40e.
Report an issue: GitHub.