nautechsystems/nautilus_trader · error
Failed to extract PyStrategy: {e}
Error message
Failed to extract PyStrategy: {e} What it means
`prepare_python_strategy_instance` extracts the supplied Python strategy object into `PyRefMut<PyStrategy>` to configure it. PyO3 extraction fails unless the object's class inherits from the Rust-backed `PyStrategy` base (`nautilus_trader.trading.strategy.Strategy`), producing this error.
Source
Thrown at crates/system/src/python/registration.rs:214
self.validate_actor_or_strategy_registration()?;
let existing_order_id_tags: Vec<&str> =
self.strategy_ids.iter().map(StrategyId::get_tag).collect();
let strategy_id = Python::attach(|py| -> anyhow::Result<StrategyId> {
let bound = strategy.bind(py);
let config_instance = bound
.getattr("config")
.ok()
.filter(|config| !config.is_none());
let class_name = bound.get_type().name()?.to_string();
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_instance.as_ref() {
configure_py_strategy(&mut py_strategy_ref, config_obj)?;
}
// Mirrors the native path: a configured ID is kept, otherwise the runtime class name
// takes the configured order ID tag, or the next positional tag
let runtime_order_id_tag = py_strategy_ref.order_id_tag();
let strategy_id = if let Some(strategy_id) = py_strategy_ref.configured_strategy_id() {
strategy_id
} else {
let order_id_tag = normalize_order_id_tag(runtime_order_id_tag.as_deref())
.map_or_else(
|| format!("{:03}", existing_order_id_tags.len()),
str::to_string,
);
StrategyId::new_checked(format!("{class_name}-{order_id_tag}"))?
};View on GitHub (pinned to 18893faf8b)
Solutions
- Make the strategy class inherit from `nautilus_trader.trading.strategy.Strategy`.
- Pass the instantiated strategy object (not the class or config) to the add-strategy API.
- Confirm the strategy and nautilus_trader Rust core come from the same installed version.
Example fix
// before
class MyStrategy:
def on_start(self): ...
// after
from nautilus_trader.trading.strategy import Strategy
class MyStrategy(Strategy):
def on_start(self): ... Defensive patterns
Strategy: type-guard
Validate before calling
from nautilus_trader.trading.strategy import Strategy assert isinstance(my_strategy, Strategy), "strategy must subclass Strategy"
Type guard
def is_strategy(obj) -> bool:
from nautilus_trader.trading.strategy import Strategy
return isinstance(obj, Strategy) Try / catch
try:
trader.add_strategy(strategy)
except Exception as e:
if "Failed to extract PyStrategy" in str(e):
raise TypeError(f"{type(strategy).__name__} must subclass nautilus_trader Strategy") from e
raise Prevention
- Always subclass nautilus_trader.trading.strategy.Strategy.
- Add an isinstance check in factory/factory-from-config code before adding strategies.
- Keep one nautilus_trader version in the environment.
When it happens
Trigger: Calling `add_python_strategy_instance` (via trader add_strategy) with a Python object that does not subclass `Strategy` — e.g. a plain class with the right method names, a config, or an object of an incompatible strategy base.
Common situations: Custom strategy forgetting to inherit `nautilus_trader.trading.strategy.Strategy`; passing a StrategyConfig instead of the strategy instance; mixing strategy classes from different nautilus_trader versions.
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
- Invalid `strategy_id` type
- Failed to extract PyStrategy: {e}
- Controller must inherit from `nautilus_trader.trading.Contro
- Failed to downcast to PyStrategy: {e}
- Failed to extract PyDataActor: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/28f66d324dc85f83.
Report an issue: GitHub.