nautechsystems/nautilus_trader · error
Failed to extract PyDataActor: {e}
Error message
Failed to extract PyDataActor: {e} What it means
Raised when Rust code cannot extract a `PyRefMut<PyDataActor>` from a Python object passed as an actor during actor registration (registering the actor and reading its id). `extract` fails when the Python object is not actually an instance of the `PyDataActor` class (or a subclass) expected by the Rust binding, so registration aborts with this anyhow-wrapped error.
Source
Thrown at crates/common/src/python/actor.rs:2842
/// Applies optional config overrides and stores a weak reference to the Python instance used for
/// method dispatch. Missing or unreadable attributes are ignored, and non-boolean `log_events` or
/// `log_commands` values leave the existing settings unchanged. When neither the config nor
/// `DataActor.__init__` supplies an ID, the runtime class name replaces the shared default so
/// subclasses that skip the base initializer still receive distinct IDs.
///
/// # Errors
///
/// Returns an error if the actor cannot be extracted, its configured `actor_id` is neither an
/// [`ActorId`] nor a valid ID string, its class-derived ID is invalid, or its Python instance
/// cannot be weakly referenced.
pub fn prepare_python_actor(
actor_obj: &Bound<'_, PyAny>,
config: Option<&Bound<'_, PyAny>>,
) -> anyhow::Result<ActorId> {
let mut actor = actor_obj
.extract::<PyRefMut<PyDataActor>>()
.map_err(Into::<PyErr>::into)
.map_err(|e| anyhow::anyhow!("Failed to extract PyDataActor: {e}"))?;
if let Some(config) = config {
if let Some(actor_id) = config
.getattr("actor_id")
.ok()
.filter(|actor_id| !actor_id.is_none())
{
let actor_id = if let Ok(actor_id) = actor_id.extract::<ActorId>() {
actor_id
} else if let Ok(actor_id) = actor_id.extract::<String>() {
ActorId::new_checked(&actor_id)?
} else {
anyhow::bail!("Invalid `actor_id` type");
};
actor.set_actor_id(actor_id);
}
if let Some(log_events) = extract_bool_config_attr(config, "log_events") {View on GitHub (pinned to 18893faf8b)
Solutions
- Ensure the object passed to registration is created via the correct Python factory/base class that produces a `PyDataActor`-backed object (subclass the provided Actor/DataActor base, do not pass arbitrary objects).
- Check that you are passing the actor object as the correct argument (not swapped with config) to the registration call.
- Verify you are not mixing versions of the library where the actor class layout changed; reinstall/rebuild the package consistently.
- Print `type(actor_obj)` and its MRO in Python to confirm it derives from the expected base before registering.
Example fix
# before
actor = MyCustomThing() # not a PyDataActor-backed instance
register_actor(actor, config)
# after
from nautilus_trader.common.actor import Actor
class MyActor(Actor): # backed by PyDataActor on the Rust side
...
actor = MyActor(config=config)
register_actor(actor, config) Defensive patterns
Strategy: type-guard
Validate before calling
# Python, before registration
from nautilus_trader.common.actor import Actor
assert isinstance(actor, Actor), f'{type(actor)} is not a supported Actor type' Type guard
def is_registrable_actor(obj) -> bool:
from nautilus_trader.common.actor import Actor
return isinstance(obj, Actor) Try / catch
match register_actor(&actor_obj, config) {
Err(e) => eprintln!("actor registration failed: {e:#}"),
Ok(id) => println!("registered actor {id}"),
} Prevention
- Always subclass the library-provided Actor/DataActor base classes
- Create actors via the documented factory functions, not raw classes
- Confirm argument order (actor, config) when calling registration
- Keep library versions consistent across install and build
When it happens
Trigger: Passing a Python object to the actor registration function (crates/common/src/python/actor.rs:2842) that is not a `PyDataActor` subclass — e.g. a plain Actor/Strategy class not derived from the required Python base, a wrong wrapper, or passing None/misordered arguments so the wrong object lands in `actor_obj`.
Common situations: Mixing actor base classes across API versions (actor created from the wrong factory or module), forgetting to subclass the required Python `Actor`/`DataActor` base that is backed by `PyDataActor`, or refactors that changed the registration entry point while callers still pass legacy objects.
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
- Python on_book failed: {e}
- Python on_mark_price failed: {e}
- Python on_index_price failed: {e}
- Python on_funding_rate failed: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/4a33a030671aded0.
Report an issue: GitHub.