nautechsystems/nautilus_trader · error

Failed to register PyDataActor: {e}

Error message

Failed to register PyDataActor: {e}

What it means

NautilusTrader throws this when a Python actor object implementing the PyDataActor trait fails during its `register(trader_id, clock, cache)` call while being attached to a trader. The actor's own registration logic (e.g. subscribing, state transitions) raised a Python error, which is wrapped in an anyhow error. It means the actor could not be fully initialized inside the trading system.

Source

Thrown at crates/system/src/python/registration.rs:434

    fn register_python_data_actor(
        &mut self,
        actor: &Py<PyAny>,
        component_id: ComponentId,
    ) -> anyhow::Result<()> {
        let clock = self.create_component_clock(component_id);
        let trader_id = self.trader_id;
        let cache = self.cache.clone();

        Python::attach(|py| -> anyhow::Result<()> {
            let py_actor = actor.bind(py);
            let mut py_data_actor_ref = py_actor
                .extract::<PyRefMut<PyDataActor>>()
                .map_err(Into::<PyErr>::into)
                .map_err(|e| anyhow::anyhow!("Failed to extract PyDataActor: {e}"))?;

            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(())
        })

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Read the chained `{e}` message to find the underlying Python exception and fix the actor code that raised it
  2. Verify all actor config values are valid before adding the actor to the trader
  3. Confirm any clients/adapters the actor's subscriptions depend on are registered before the actor
  4. Run the actor registration in isolation with logging enabled to pinpoint the failing hook

Example fix

// before: actor with bad config raises inside register
trader.add_actor(MyActor(config=MyActorConfig(instrument_id="INVALID")))
// after: validate first
instrument_id = InstrumentId.from_str("BTCUSDT.BINANCE")  # raises early if bad
trader.add_actor(MyActor(config=MyActorConfig(instrument_id=instrument_id)))
Defensive patterns

Strategy: try-catch

Validate before calling

# before adding actor
assert isinstance(actor, Actor), "actor must subclass nautilus_trader Actor"
actor.validate_config()  # or validate config fields manually

Type guard

def is_valid_actor(obj) -> bool:
    from nautilus_trader.common.actor import Actor
    return isinstance(obj, Actor)

Try / catch

try:
    trader.add_data_actor(actor)
except Exception as e:
    logging.exception("actor registration failed: %s", e)
    raise

Prevention

When it happens

Trigger: Calling `trader.add_data_actor(actor)` (or adding an actor via a node config) where the actor's `register()` — or any code it calls such as `subscribe_*` in on_start registration paths — raises a Python exception. Any Python-side error inside the actor during registration surfaces as this message.

Common situations: Actor constructors or registration hooks referencing unavailable config, importing modules that are missing, misconfigured subscription parameters (invalid instrument IDs, client IDs), or bugs in custom actor code that run during registration.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/a4b0985e28064786. Report an issue: GitHub.