nautechsystems/nautilus_trader · error

Failed to register PyStrategy: {e}

Error message

Failed to register PyStrategy: {e}

What it means

After extraction succeeds, `register_python_strategy_components` calls the strategy's Rust `register(trader_id, clock, cache, portfolio)` and wraps any error it returns as this message. This fires when the strategy's own registration against trader/clock/cache/portfolio fails (e.g. invalid trader_id or a component-state error inside register).

Source

Thrown at crates/system/src/python/registration.rs:306

        &mut self,
        strategy: &Py<PyAny>,
        strategy_id: StrategyId,
    ) -> anyhow::Result<()> {
        let clock = self.create_component_clock(ComponentId::from(strategy_id));
        let trader_id = self.trader_id;
        let cache = self.cache.clone();
        let portfolio = self.portfolio.clone();

        Python::attach(|py| -> anyhow::Result<()> {
            let py_strategy = strategy.bind(py);
            let mut py_strategy_ref = py_strategy
                .extract::<PyRefMut<PyStrategy>>()
                .map_err(Into::<PyErr>::into)
                .map_err(|e| anyhow::anyhow!("Failed to extract PyStrategy: {e}"))?;

            py_strategy_ref
                .register(trader_id, clock, cache, portfolio)
                .map_err(|e| anyhow::anyhow!("Failed to register PyStrategy: {e}"))?;

            log::debug!(
                "Internal PyStrategy registered: {}",
                py_strategy_ref.is_registered()
            );

            Ok(())
        })?;

        Python::attach(|py| -> anyhow::Result<()> {
            let py_strategy = strategy.bind(py);
            let py_strategy_ref = py_strategy
                .cast::<PyStrategy>()
                .map_err(|e| anyhow::anyhow!("Failed to downcast to PyStrategy: {e}"))?;
            py_strategy_ref.borrow().register_in_global_registries()?;
            Ok(())
        })?;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Read the inner `{e}` for the precise failure inside PyStrategy::register.
  2. Verify the trader_id and node configuration are valid and consistent.
  3. Ensure each strategy instance is registered only once and the node's clock/cache/portfolio are initialized before adding strategies.

Example fix

// before
node.trader.add_strategy(MyStrategy(StrategyConfig(strategy_id="invalid id!")))

// after
from nautilus_trader.model.identifiers import StrategyId
node.trader.add_strategy(MyStrategy(StrategyConfig(strategy_id=StrategyId("MyStrategy-001"))))
Defensive patterns

Strategy: validation

Validate before calling

from nautilus_trader.model.identifiers import StrategyId
cfg = MyStrategyConfig(strategy_id=StrategyId("MyStrategy-001"))
assert cfg.strategy_id and len(str(cfg.strategy_id)) > 0

Try / catch

try:
    trader.add_strategy(strategy)
except Exception as e:
    if "Failed to register PyStrategy" in str(e):
        logging.error("register() failed inside strategy: %s — check trader_id/config", e)
    raise

Prevention

When it happens

Trigger: Calling `add_python_strategy_instance` where the strategy's internal `register` returns Err — e.g. malformed TraderId, a registration invariant inside PyStrategy failing, or a Python exception surfaced from the register path.

Common situations: Misconfigured trader_id in the node config; registering a strategy twice into the same trader; underlying clock/cache not initialized before adding strategies.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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