nautechsystems/nautilus_trader · error
Failed to downcast to PyDataActor: {e}
Error message
Failed to downcast to PyDataActor: {e} What it means
This error is raised when a Python object passed as an actor cannot be cast to the `PyDataActor` trait object during registration into global registries. It means the object does not actually implement the PyDataActor interface expected by the system, so `register_in_global_registries()` cannot proceed.
Source
Thrown at crates/system/src/python/registration.rs:449
py_data_actor_ref
.register(trader_id, clock, cache)
.map_err(|e| anyhow::anyhow!("Failed to register PyDataActor: {e}"))?;
log::debug!(
"Internal PyDataActor registered: {}, state: {:?}",
py_data_actor_ref.is_registered(),
py_data_actor_ref.state()
);
Ok(())
})?;
Python::attach(|py| -> anyhow::Result<()> {
let py_actor = actor.bind(py);
let py_data_actor_ref = py_actor
.cast::<PyDataActor>()
.map_err(|e| anyhow::anyhow!("Failed to downcast to PyDataActor: {e}"))?;
py_data_actor_ref.borrow().register_in_global_registries()?;
Ok(())
})
}
/// Rejects a component ID this trader already tracks, whatever kind registered it.
///
/// Duplicate adds are otherwise checked only within a kind, so an actor sharing an ID with a
/// live strategy would overwrite that strategy's clock, registry entries, and wrapper, and a
/// rollback would then remove state the attempt did not create. The lifecycle collections are
/// checked alongside the clocks because a component registered externally and tracked through
/// `add_*_id_for_lifecycle` has no trader-owned clock.
fn ensure_component_id_available(&self, component_id: ComponentId) -> anyhow::Result<()> {
let id = component_id.inner();
let tracked = self.clocks.contains_key(&component_id)
|| self.actor_ids.iter().any(|actor_id| actor_id.inner() == id)
|| self
.strategy_idsView on GitHub (pinned to 18893faf8b)
Solutions
- Make the Python class inherit from `nautilus_trader.common.actor.Actor` (or the appropriate Actor subclass)
- Check you are passing an actor instance, not a class or a strategy
- Verify your nautilus_trader Python package version matches the Rust core version
- Inspect the chained `{e}` PyO3 downcast error for the exact type mismatch
Example fix
// before
class MyActor: # not an Actor
...
// after
from nautilus_trader.common.actor import Actor
class MyActor(Actor):
... Defensive patterns
Strategy: type-guard
Validate before calling
from nautilus_trader.common.actor import Actor
assert isinstance(obj, Actor), f"{type(obj)} is not an Actor" Type guard
from nautilus_trader.common.actor import Actor
def is_pydata_actor(obj) -> bool:
return isinstance(obj, Actor) Try / catch
try:
trader.add_data_actor(obj)
except Exception as e:
if "downcast" in str(e):
raise TypeError(f"{obj!r} must subclass Actor") from e
raise Prevention
- Always subclass nautilus_trader.common.actor.Actor for data actors
- Pass instances, not classes, to registration APIs
- Keep nautilus_trader Python and core versions in sync
When it happens
Trigger: Calling `register_python_data_actor` (via trader/actor registration APIs) with a Python object that does not inherit from/implement the NautilusTrader `Actor` Python base (PyDataActor). PyO3's `cast::<PyDataActor>()` fails because the object lacks the Rust-side trait implementation exposed to Python.
Common situations: Passing a plain Python class, a Strategy, or a custom object where an Actor is expected; forgetting to subclass `nautilus_trader.common.actor.Actor`; mixing API versions where the base class changed.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- Invalid `exec_algorithm_id`/`actor_id` type
- Failed to register PyDataActor: {e}
- Invalid `order_id_tag` type: {e}
- Invalid `external_order_claims` type: {e}
- Invalid `external_order_claims` instrument ID {claim}: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/2cf1d7de739e579a.
Report an issue: GitHub.