nautechsystems/nautilus_trader · error

Failed to import module {module_name}: {e}

Error message

Failed to import module {module_name}: {e}

What it means

create_importable_component imports a Python module by dotted path (via py.import) to instantiate an actor, strategy, or exec algorithm from its config. This error is thrown when Python's import machinery cannot import the specified module (ModuleNotFoundError, syntax error, or import-time exception).

Source

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

) -> PyResult<Py<PyAny>> {
    let Some((module_name, class_name)) = component_path.split_once(':') else {
        return Err(to_pyvalue_err(format!(
            "{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>,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify the module string in the config matches the importable dotted path, e.g. 'strategies.my_strategy'.
  2. Ensure the package is importable from the backtest entrypoint: pip install -e . or set PYTHONPATH to the project root.
  3. Import the module manually in the same interpreter (`python -c "import strategies.my_strategy"`) to see the underlying import error.
  4. Fix any exceptions raised at module import time shown in the chained {e} message.

Example fix

# before
config = MyStrategyConfig(module="my_strategy")  # not on sys.path
# after
# run from repo root with strategies/ package installed:
config = MyStrategyConfig(module="strategies.my_strategy")
Defensive patterns

Strategy: validation

Validate before calling

import importlib
def assert_importable(module_name: str):
    try:
        importlib.import_module(module_name)
    except ImportError as e:
        raise SystemExit(f"Fix module path/PYTHONPATH before running backtest: {e}")
assert_importable(config.module)

Try / catch

try:
    node.add_actor_from_config(actor_config)
except Exception as e:
    if "Failed to import module" in str(e):
        raise SystemExit(f"Check module string and PYTHONPATH: {e}") from e
    raise

Prevention

When it happens

Trigger: Adding an actor/strategy/exec algorithm from config (py_add_actor_from_config, py_add_strategy_from_config, py_add_exec_algorithm_from_config) where the config's module path is wrong, the module isn't on sys.path, or importing the module itself raises.

Common situations: Typo in the module string ('my_strat' vs 'my_strategy'); running the backtest script from a directory where the package isn't importable (missing PYTHONPATH or no pip install -e .); an exception at module import time (bad env var, missing third-party dependency).

Related errors


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