nautechsystems/nautilus_trader · error

Failed to get class {class_name}: {e}

Error message

Failed to get class {class_name}: {e}

What it means

Raised when the actor's module imports successfully but `getattr(class_name)` on the module fails, i.e. the expected actor class does not exist in that module. The `PyErr` (usually `AttributeError: module ... has no attribute ...`) is wrapped into this anyhow error with the class name included. This happens after the import step, so the module itself was found.

Source

Thrown at crates/live/src/python/node.rs:1182

        // Extract module and class name from actor_path
        let parts: Vec<&str> = config.actor_path.split(':').collect();
        if parts.len() != 2 {
            return Err(to_pyvalue_err(
                "actor_path must be in format 'module.path:ClassName'",
            ));
        }
        let (module_name, class_name) = (parts[0], parts[1]);

        log::info!("Importing actor from module: {module_name} class: {class_name}");

        let (python_actor, actor_id) =
            Python::attach(|py| -> anyhow::Result<(Py<PyAny>, ActorId)> {
                let actor_module = py
                    .import(module_name)
                    .map_err(|e| anyhow::anyhow!("Failed to import module {module_name}: {e}"))?;
                let actor_class = actor_module
                    .getattr(class_name)
                    .map_err(|e| anyhow::anyhow!("Failed to get class {class_name}: {e}"))?;

                let config_instance =
                    create_config_instance(py, &config.config_path, &config.config)?;

                let python_actor = if let Some(config_obj) = config_instance.as_ref() {
                    actor_class.call1((config_obj,))?
                } else {
                    actor_class.call0()?
                };

                log::debug!("Created Python actor instance: {python_actor:?}");

                let actor_id = prepare_python_actor(&python_actor, config_instance.as_ref())?;

                Ok((python_actor.unbind(), actor_id))
            })
            .map_err(to_pyruntime_err)?;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Confirm the class exists: `python -c "import <module>; print(<module>.<class_name>)"`.
  2. Fix the `class_name` in the actor config to match the definition exactly (case-sensitive).
  3. If the class moved, re-export it at module level (`from .impl import MyClass`) or update the config path.
  4. Check for typos and recent renames after upgrading the codebase.

Example fix

# before
config = ImportableActorConfig(module='strats.momentum', class_name='MomentumStrat')
# after (class is actually named MomentumStrategy)
config = ImportableActorConfig(module='strats.momentum', class_name='MomentumStrategy')
Defensive patterns

Strategy: validation

Validate before calling

# Verify the class exists before adding the actor
import importlib
mod = importlib.import_module(config.module)
assert hasattr(mod, config.class_name), f"{config.class_name!r} not found in {config.module}"

Type guard

def actor_class_exists(module_name: str, class_name: str) -> bool:
    import importlib
    return hasattr(importlib.import_module(module_name), class_name)

Try / catch

try:
    node.add_actor(actor_config)
except Exception as e:
    if "Failed to get class" in str(e):
        logging.error("class %s missing in %s; check spelling/renames", actor_config.class_name, actor_config.module)
    else:
        raise

Prevention

When it happens

Trigger: Calling the node's add-actor API with a config whose `class_name` does not match any attribute of the module: misspelled class name, class defined in a submodule, class renamed in a version update, or the name refers to a non-class object.

Common situations: Copy-pasted config where the module was updated but the class name wasn't; renaming a strategy class without updating the YAML/JSON config; pointing at `package.file` but expecting the class at package level; typos in case-sensitive names.

Related errors


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