nautechsystems/nautilus_trader · critical
Failed to start strategy {strategy_id}: {start_err}; rollbac
Error message
Failed to start strategy {strategy_id}: {start_err}; rollback failed: {rollback_err} What it means
Analogous to the actor variant: when a strategy fails to start, the controller rolls back by removing the strategy via remove_strategy. If that rollback also fails, both the original start error and the rollback error are combined into this message naming the StrategyId.
Source
Thrown at crates/system/src/controller.rs:356
actor_id: ActorId,
start_err: anyhow::Error,
) -> anyhow::Error {
match self.remove_actor(&actor_id) {
Ok(()) => start_err,
Err(rollback_err) => anyhow::anyhow!(
"Failed to start actor {actor_id}: {start_err}; rollback failed: {rollback_err}"
),
}
}
fn rollback_strategy_start_failure(
&self,
strategy_id: StrategyId,
start_err: anyhow::Error,
) -> anyhow::Error {
match self.remove_strategy(&strategy_id) {
Ok(()) => start_err,
Err(rollback_err) => anyhow::anyhow!(
"Failed to start strategy {strategy_id}: {start_err}; rollback failed: {rollback_err}"
),
}
}
fn register_execute_endpoint(&self) {
let controller_id = self.core.actor_id().inner();
let handler = TypedHandler::from(move |command: &ControllerCommand| {
if let Some(mut controller) = try_get_actor_unchecked::<Self>(&controller_id) {
if let Err(e) = controller.execute(command.clone()) {
log::error!("Controller command failed for {controller_id}: {e}");
}
} else {
log::error!("Controller {controller_id} not found for command handling");
}
});
get_message_bus()View on GitHub (pinned to 18893faf8b)
Solutions
- Address the original start error ({start_err} in the message) — it is the primary cause
- Check why remove_strategy failed: duplicate registration, already-removed strategy, or a locked registry
- Ensure strategy IDs are unique across the trading system config
- Run the strategy in isolation with debug logging to isolate the start failure from the rollback failure
Defensive patterns
Strategy: try-catch
Validate before calling
// before start_created_strategy
assert!(!controller.has_strategy(&strategy_id), "strategy {strategy_id} already registered"); Try / catch
match system.start() {
Err(e) if e.to_string().contains("rollback failed") => {
log::error!("strategy start AND rollback failed — rebuild controller state: {e:#}");
}
other => other?,
} Prevention
- Enforce unique StrategyIds across the system config
- Keep strategy removal idempotent so rollback cannot fail
- Validate strategy dependencies (instruments, accounts) exist before start to avoid compounding failures
When it happens
Trigger: start_created_strategy fails during strategy start (bad config, failed on_start handler), and remove_strategy then also errors because the strategy cannot be cleanly removed from the controller's registry.
Common situations: Strategy on_start panics or errors due to missing instruments/accounts, compounded by registry inconsistency; duplicate strategy IDs causing removal to fail; strategy stuck in a starting state that blocks removal.
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
- Failed to start actor {actor_id}: {start_err}; rollback fail
- Cannot add strategy while node is running, add strategies be
- Strategy {strategy_id} is not registered with a trader
- Python on_start failed: {e}
- Python on_stop failed: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/7ba266127fb94949.
Report an issue: GitHub.