nautechsystems/nautilus_trader · error

Failed to extract PyStrategy: {e}

Error message

Failed to extract PyStrategy: {e}

What it means

Raised when the live node cannot extract a `PyRefMut<PyStrategy>` borrow from the Python strategy object during registration. This means the object registered as a strategy is not actually an instance of `PyStrategy` (or its Rust borrow cannot be taken, e.g. the object is already mutably borrowed in Python or is a different wrapper type). The registration aborts at this point.

Source

Thrown at crates/live/src/python/node.rs:1254

            .node_mut()?
            .kernel_mut()
            .trader
            .borrow_mut()
            .prepare_python_strategy_instance(&strategy)
            .map_err(to_pyruntime_err)?;

        let (external_order_instrument_ids, oms_type) = Python::attach(
            |py| -> anyhow::Result<(Option<Vec<InstrumentId>>, Option<OmsType>)> {
                let bound = strategy.bind(py);
                let config_obj = bound
                    .getattr("config")
                    .ok()
                    .filter(|config| !config.is_none());

                let mut py_strategy_ref = bound
                    .extract::<PyRefMut<PyStrategy>>()
                    .map_err(Into::<PyErr>::into)
                    .map_err(|e| anyhow::anyhow!("Failed to extract PyStrategy: {e}"))?;

                if let Some(config_obj) = config_obj.as_ref()
                    && let Some(claims) =
                        extract_external_order_instrument_ids_config_attr(config_obj)?
                {
                    py_strategy_ref.set_external_order_instrument_ids(Some(claims));
                }

                let claims = py_strategy_ref.external_order_instrument_ids();
                let oms_type = config_obj
                    .as_ref()
                    .and_then(|cfg| cfg.getattr("oms_type").ok())
                    .filter(|value| !value.is_none())
                    .and_then(|value| value.extract::<OmsType>().ok());

                Ok((claims, oms_type))
            },
        )

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify the configured class subclasses `nautilus_trader.trading.strategy.Strategy` and is instantiated (not the class object itself).
  2. Check what `{e}` reports: a `TypeError`/`ExtractErr` means wrong type; a `BorrowMutError` means the object is already checked out.
  3. Ensure the factory/`create_config_instance` path returns the strategy instance directly.
  4. Do not hold the strategy object mutably in Python code (e.g. inside a callback) while registering it.

Example fix

# before
class MyActor(Actor):  # wrong base, extract as PyStrategy fails
    ...
# after
from nautilus_trader.trading.strategy import Strategy
class MyStrategy(Strategy):
    ...
Defensive patterns

Strategy: type-guard

Validate before calling

# Ensure the configured object is a Strategy instance before registration
from nautilus_trader.trading.strategy import Strategy
obj = strategy_module(**config_kwargs)
assert isinstance(obj, Strategy), f"expected Strategy, got {type(obj).__name__}"

Type guard

def is_py_strategy(obj) -> bool:
    from nautilus_trader.trading.strategy import Strategy
    return isinstance(obj, Strategy)

Try / catch

try:
    node.trader.add_strategy(strategy)
except Exception as e:
    if "Failed to extract PyStrategy" in str(e):
        logging.error("object is not a PyStrategy (check base class/instantiation): %s", e)
    else:
        raise

Prevention

When it happens

Trigger: Registering a Python object as a strategy that is not a `PyStrategy` subclass instance (e.g. an Actor, a plain object, or a strategy built by a factory returning the wrong type), or extracting the borrow while the same object is already mutably borrowed elsewhere.

Common situations: Config `class_name` points to a class that subclasses `Actor` instead of `Strategy`; a custom factory wraps the strategy in a different container; passing the strategy class instead of an instance through a code path expecting a constructed `PyStrategy`.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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