nautechsystems/nautilus_trader · error

Failed to get class {class_name}: {e}

Error message

Failed to get class {class_name}: {e}

What it means

After successfully importing the module, create_importable_component fetches the component class with module.getattr(class_name). This error means the attribute (class name) does not exist on the imported module — or importing it as an attribute raised — so the actor/strategy/exec algorithm cannot be constructed.

Source

Thrown at crates/backtest/src/python/node.rs:484

            "{path_field} must be in format 'module.path:ClassName'",
        )));
    };

    if module_name.is_empty() || class_name.is_empty() || class_name.contains(':') {
        return Err(to_pyvalue_err(format!(
            "{path_field} must be in format 'module.path:ClassName'",
        )));
    }

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

    Python::attach(|py| -> anyhow::Result<Py<PyAny>> {
        let module = py
            .import(module_name)
            .map_err(|e| anyhow::anyhow!("Failed to import module {module_name}: {e}"))?;
        let class = module
            .getattr(class_name)
            .map_err(|e| anyhow::anyhow!("Failed to get class {class_name}: {e}"))?;
        let config_instance = create_config_instance(py, config_path, config)?;
        let component = if let Some(config_obj) = config_instance {
            class.call1((config_obj,))?
        } else {
            class.call0()?
        };
        Ok(component.unbind())
    })
    .map_err(to_pyruntime_err)
}

pub(crate) fn create_config_instance<'py>(
    py: Python<'py>,
    config_path: &str,
    config: &HashMap<String, serde_json::Value>,
) -> anyhow::Result<Option<Bound<'py, PyAny>>> {
    if config_path.is_empty() && config.is_empty() {
        log::debug!("No config_path or empty config, using None");

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check the class name string in the config matches the top-level class exactly (case-sensitive).
  2. Confirm the class is defined at module scope, not nested in a function or another module.
  3. Run `python -c "from <module> import <class>"` to reproduce the exact getattr failure.
  4. Update stale configs after refactors/renames of the strategy or actor class.

Example fix

# before
config = MyStrategyConfig(module="strategies.my_strategy", class_name="MyStrat")  # renamed
# after
config = MyStrategyConfig(module="strategies.my_strategy", class_name="MyStrategy")
Defensive patterns

Strategy: validation

Validate before calling

import importlib
def assert_class_exists(module_name: str, class_name: str):
    mod = importlib.import_module(module_name)
    assert hasattr(mod, class_name), f"{module_name} has no attribute {class_name}"
assert_class_exists(config.module, config.class_name)

Try / catch

try:
    node.add_strategy_from_config(strategy_config)
except Exception as e:
    if "Failed to get class" in str(e):
        raise SystemExit(f"Class name mismatch in config: {e}") from e
    raise

Prevention

When it happens

Trigger: py_add_actor_from_config / py_add_strategy_from_config / py_add_exec_algorithm_from_config with a config whose class name is misspelled, is not defined at module top level, or was renamed in a newer version of the user's code.

Common situations: Renaming the strategy class but not the config; class defined inside a function or submodule (e.g. strategies.my_strategy.MyStrategy vs strategies.MyStrategy); typos in casing ('myStrategy' vs 'MyStrategy').

Related errors


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