nautechsystems/nautilus_trader · error
Failed to extract PyDataActor: {e}
Error message
Failed to extract PyDataActor: {e} What it means
When adding a Python exec algorithm to the backtest engine, the provided object must be extractable as a PyDataActor (a registered Rust wrapper type for Python actors). PyO3's extract failed, so the object is not a recognized actor/strategy instance.
Source
Thrown at crates/backtest/src/python/engine.rs:963
) -> PyResult<()> {
Self::ensure_can_add_exec_algorithm(engine)?;
if Self::try_add_py_execution_algorithm(engine, exec_algorithm)? {
return Ok(());
}
let actor_id = Python::attach(|py| -> anyhow::Result<ActorId> {
let bound = exec_algorithm.bind(py);
let config_instance = bound
.getattr("config")
.ok()
.filter(|config| !config.is_none());
let mut py_data_actor_ref = bound
.extract::<PyRefMut<PyDataActor>>()
.map_err(Into::<PyErr>::into)
.map_err(|e| anyhow::anyhow!("Failed to extract PyDataActor: {e}"))?;
if let Some(config_obj) = config_instance.as_ref() {
let id_attr = config_obj
.getattr("exec_algorithm_id")
.ok()
.filter(|v| !v.is_none())
.or_else(|| config_obj.getattr("actor_id").ok().filter(|v| !v.is_none()));
if let Some(id_value) = id_attr {
let actor_id_val = if let Ok(eaid) = id_value.extract::<ExecAlgorithmId>() {
ActorId::new(eaid.inner())
} else if let Ok(aid) = id_value.extract::<ActorId>() {
aid
} else if let Ok(aid_str) = id_value.extract::<String>() {
ActorId::new_checked(&aid_str)?
} else {
anyhow::bail!("Invalid `exec_algorithm_id`/`actor_id` type");
};View on GitHub (pinned to 18893faf8b)
Solutions
- Instantiate the exec algorithm from a class that inherits nautilus_trader.trading.strategy.Strategy (or the actor base) and pass the instance.
- Verify you are passing the object, not the class: add_exec_algorithm(MyAlgo(config)), not add_exec_algorithm(MyAlgo).
- Check that the nautilus_trader Python package version matches the Rust/PyO3 bindings in use.
Example fix
# before engine.add_python_exec_algorithm(MyExecAlgo, config) # class passed # after engine.add_python_exec_algorithm(MyExecAlgo(config), config)
Defensive patterns
Strategy: type-guard
Validate before calling
from nautilus_trader.common.actor import Actor assert isinstance(exec_algorithm, Actor), "exec algorithm must be an Actor/Strategy instance"
Type guard
def is_py_data_actor(obj) -> bool:
from nautilus_trader.common.actor import Actor
return isinstance(obj, Actor) and not isinstance(obj, type)
Try / catch
try:
engine.add_python_exec_algorithm(algo, config)
except Exception as e:
if "Failed to extract PyDataActor" in str(e):
raise TypeError(f"{algo!r} is not an Actor instance; pass an instantiated Strategy") from e
raise
Prevention
- Always pass instantiated actor/strategy objects, never classes or functions.
- Subclass nautilus_trader Strategy/Actor for all exec algorithms.
- Keep the installed nautilus_trader Python package in sync with the Rust bindings.
When it happens
Trigger: Calling add_python_exec_algorithm with an object that is not an instance of a class deriving from nautilus_trader's Actor/Strategy base (e.g. a plain Python object, a function, or a class instead of an instance).
Common situations: Passing the exec algorithm class instead of an instantiated object; passing an algorithm built on an older/other base class; passing a non-actor callable such as a raw function configured via exec_algorithm.
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
- BacktestEngineConfig.controller for importable controller '{
- Failed to convert historical data to Python: unsupported typ
- Failed to convert instrument to Python: {e}
- Failed to convert batched deltas to Python: {e}
- Invalid book_snapshot_output: '{book_snapshot_output}'. Expe
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/aec108251cd01d79.
Report an issue: GitHub.