nautechsystems/nautilus_trader · error
Cannot add components to disposed trader
Error message
Cannot add components to disposed trader
What it means
validate_actor_or_strategy_registration allows adding components only in PreInitialized, Ready, Starting, Stopped, or Running states. Once the trader is Disposed, its resources are torn down and no new actors or strategies may be added, so any registration attempt fails with this message.
Source
Thrown at crates/system/src/trader.rs:837
);
Ok(())
}
/// Validates that the trader is in a valid state for actor and strategy registration.
///
/// Actors and strategies can be added while the trader is `PreInitialized`, `Ready`,
/// `Stopped`, or `Running`. This enables the [`Controller`](crate::controller::Controller)
/// to add them at runtime.
pub(crate) fn validate_actor_or_strategy_registration(&self) -> anyhow::Result<()> {
match self.state {
ComponentState::PreInitialized
| ComponentState::Ready
| ComponentState::Starting
| ComponentState::Stopped
| ComponentState::Running => Ok(()),
ComponentState::Disposed => {
anyhow::bail!("Cannot add components to disposed trader")
}
_ => anyhow::bail!("Cannot add components in current state: {}", self.state),
}
}
/// Validates that the trader is in a valid state for execution algorithm registration.
pub(crate) fn validate_exec_algorithm_registration(&self) -> anyhow::Result<()> {
match self.state {
ComponentState::PreInitialized | ComponentState::Ready | ComponentState::Stopped => {
Ok(())
}
ComponentState::Running => {
anyhow::bail!("Cannot add execution algorithms to running trader")
}
ComponentState::Disposed => {
anyhow::bail!("Cannot add components to disposed trader")
}
_ => anyhow::bail!(View on GitHub (pinned to 18893faf8b)
Solutions
- Create a new Trader instance instead of reusing the disposed one.
- Move all add_actor/add_strategy calls before dispose(), typically right after construction or after stop() if restarting.
- Track trader state (e.g. check the component state) before registration calls.
Example fix
// before trader.dispose(); trader.add_strategy(strategy)?; // bails: disposed // after trader.dispose(); let trader = Trader::new(trader_id, ...); trader.add_strategy(strategy)?;
Defensive patterns
Strategy: validation
Validate before calling
if trader.state == ComponentState::Disposed {
// create a new trader before adding components
} Type guard
fn can_register(trader: &Trader) -> bool {
!matches!(trader.state, ComponentState::Disposed)
} Try / catch
match trader.add_strategy(strategy) {
Err(e) if e.to_string().contains("disposed") => {
let mut trader = Trader::new(trader_id, ...);
trader.add_strategy(strategy)?;
}
other => other?,
} Prevention
- Treat Trader as single-use: rebuild after dispose
- Register all components during setup, never in shutdown paths
- Check trader state before every registration call
When it happens
Trigger: Calling add_actor, add_strategy, add_actor_from_importable_config, add_strategy_from_importable_config, or prepare_python_strategy_instance after trader.dispose() (or equivalent teardown) has moved the trader's state to ComponentState::Disposed.
Common situations: Reusing a trader across backtest runs without recreating it; calling add_strategy in shutdown/cleanup code that runs after dispose; long-lived services holding a disposed trader after a stop-and-dispose sequence.
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
- Cannot add components in current state: {}
- Cannot add execution algorithms to running trader
- Active execution intent {intent_id} was not found
- DataActor {} must be registered before calling `clock_mut()`
- DataActor {} must be registered before calling `clock()` - t
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/bc512acb4fff1103.
Report an issue: GitHub.