{"record":{"id":"aec108251cd01d79","repo":"nautechsystems/nautilus_trader","slug":"failed-to-extract-pydataactor-e-aec108","errorCode":null,"errorMessage":"Failed to extract PyDataActor: {e}","messagePattern":"Failed to extract PyDataActor: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/backtest/src/python/engine.rs","lineNumber":963,"sourceCode":"    ) -> PyResult<()> {\n        Self::ensure_can_add_exec_algorithm(engine)?;\n\n        if Self::try_add_py_execution_algorithm(engine, exec_algorithm)? {\n            return Ok(());\n        }\n\n        let actor_id = Python::attach(|py| -> anyhow::Result<ActorId> {\n            let bound = exec_algorithm.bind(py);\n\n            let config_instance = bound\n                .getattr(\"config\")\n                .ok()\n                .filter(|config| !config.is_none());\n\n            let mut py_data_actor_ref = bound\n                .extract::<PyRefMut<PyDataActor>>()\n                .map_err(Into::<PyErr>::into)\n                .map_err(|e| anyhow::anyhow!(\"Failed to extract PyDataActor: {e}\"))?;\n\n            if let Some(config_obj) = config_instance.as_ref() {\n                let id_attr = config_obj\n                    .getattr(\"exec_algorithm_id\")\n                    .ok()\n                    .filter(|v| !v.is_none())\n                    .or_else(|| config_obj.getattr(\"actor_id\").ok().filter(|v| !v.is_none()));\n\n                if let Some(id_value) = id_attr {\n                    let actor_id_val = if let Ok(eaid) = id_value.extract::<ExecAlgorithmId>() {\n                        ActorId::new(eaid.inner())\n                    } else if let Ok(aid) = id_value.extract::<ActorId>() {\n                        aid\n                    } else if let Ok(aid_str) = id_value.extract::<String>() {\n                        ActorId::new_checked(&aid_str)?\n                    } else {\n                        anyhow::bail!(\"Invalid `exec_algorithm_id`/`actor_id` type\");\n                    };","sourceCodeStart":945,"sourceCodeEnd":981,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/backtest/src/python/engine.rs#L945-L981","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"# before\nengine.add_python_exec_algorithm(MyExecAlgo, config)  # class passed\n# after\nengine.add_python_exec_algorithm(MyExecAlgo(config), config)","handlingStrategy":"type-guard","validationCode":"from nautilus_trader.common.actor import Actor\nassert isinstance(exec_algorithm, Actor), \"exec algorithm must be an Actor/Strategy instance\"\n","typeGuard":"def is_py_data_actor(obj) -> bool:\n    from nautilus_trader.common.actor import Actor\n    return isinstance(obj, Actor) and not isinstance(obj, type)\n","tryCatchPattern":"try:\n    engine.add_python_exec_algorithm(algo, config)\nexcept Exception as e:\n    if \"Failed to extract PyDataActor\" in str(e):\n        raise TypeError(f\"{algo!r} is not an Actor instance; pass an instantiated Strategy\") from e\n    raise\n","preventionTips":["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."],"tags":["python","pyo3","backtest","exec-algorithm"],"backgroundTag":"type-mismatch","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}