nautechsystems/nautilus_trader · error
Failed to restore strategy
Error message
Failed to restore strategy {strategy_id} state: {e:#} What it means
Raised in `Trader::load_state` when a strategy's registered `on_load` state-restoration callback returns an error. The persisted state was read from the cache successfully, but the strategy could not restore it, so recovery aborts with this message.
Solutions
- Inspect the wrapped `{e:#}` for the exact restore failure and align the load callback with the persisted schema
- Ensure the strategy implementation/version that saved the state matches the one restoring it; add migration logic to the load callback if needed
- Delete the strategy's stale persisted key so it starts with empty state, then let it re-save
- Keep library versions consistent between state-saving and state-restoring runs
Defensive patterns
Strategy: try-catch
Validate before calling
// round-trip check the strategy state before relying on recovery let state = cache.load_strategy_state(&strategy_id)?; strategy.test_restore(state.clone())?;
Try / catch
do {
system.start_with_recovery()
} catch e if e.contains("Failed to restore strategy") => {
// migrate the schema or delete the stale key, then restart
} Prevention
- Version and migration-test strategy state schemas across releases
- Save/restore with the identical strategy type and library version
- Round-trip test save/load in CI for every strategy
- Delete stale keys intentionally when a strategy's state layout changes
When it happens
Trigger: Trader start with state recovery enabled; the cache returns non-empty state for the strategy and the strategy's `load` callback errors — typically because the saved payload does not match the strategy's current state schema (version upgrade, changed fields, wrong strategy type).
Common situations: Restarting after a nautilus upgrade with state saved by the older version; refactoring a strategy's saved-state struct without a migration; a cache shared between configurations containing state for a different strategy instance.
Related errors
- Failed to load strategy
- Failed to restore actor
- Cannot add strategy while node is running, add strategies…
- Failed to load actor
- Strategy state callback not found
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/c516580c885a469a.
Report an issue: GitHub.
Appendix: source
Thrown at crates/system/src/trader.rs:1606
};
(callbacks.load)(actor_id.inner(), state)
.map_err(|e| anyhow::anyhow!("Failed to restore actor {actor_id} state: {e:#}"))?;
}
for (strategy_id, callbacks) in strategy_callbacks {
let state = cache
.borrow()
.load_strategy_state(&strategy_id)
.map_err(|e| {
anyhow::anyhow!("Failed to load strategy {strategy_id} state: {e:#}")
})?;
let Some(state) = state.filter(|state| !state.is_empty()) else {
continue;
};
(callbacks.load)(strategy_id.inner(), state).map_err(|e| {
anyhow::anyhow!("Failed to restore strategy {strategy_id} state: {e:#}")
})?;
}
Ok(())
}
/// Saves actor and strategy state in registration order.
///
/// Empty state is persisted, while a cache without database backing does not invoke
/// component callbacks. All callbacks and updates receive an attempt before errors return.
///
/// # Errors
///
/// Returns an error containing every component callback or persistence failure.
pub(crate) fn save_state(trader: &Rc<RefCell<Self>>) -> anyhow::Result<()> {
let (cache, actor_callbacks, strategy_callbacks) = {
let trader = trader.borrow();
let actor_callbacks = trader.actor_state_callbacks()?;View on GitHub (pinned to 18893faf8b)