nautechsystems/nautilus_trader · error · anyhow::Error

Failed to import {module_name}: {e}

Error message

Failed to import {module_name}: {e}

What it means

After splitting filter_callable, the module part is imported with PyModule::import inside Python::attach. This error wraps the Python ImportError when the module cannot be imported — it does not exist on sys.path or a transitive import inside it failed.

Source

Thrown at crates/adapters/interactive_brokers/src/providers/instruments.rs:1790

    fn passes_filter_callable(&self, instrument: &InstrumentAny) -> anyhow::Result<bool> {
        let Some(filter_callable) = self.config.filter_callable.as_deref() else {
            return Ok(true);
        };

        #[cfg(feature = "python")]
        {
            use nautilus_model::python::instruments::instrument_any_to_pyobject;
            use pyo3::{prelude::*, types::PyModule};

            Python::attach(|py| {
                let (module_name, callable_name) =
                    filter_callable.rsplit_once('.').ok_or_else(|| {
                        anyhow::anyhow!(
                            "Invalid filter_callable path {filter_callable:?}; expected module.callable"
                        )
                    })?;
                let callable = PyModule::import(py, module_name)
                    .map_err(|e| anyhow::anyhow!("Failed to import {module_name}: {e}"))?
                    .getattr(callable_name)
                    .map_err(|e| anyhow::anyhow!("Failed to resolve {filter_callable}: {e}"))?;
                let py_instrument = instrument_any_to_pyobject(py, instrument.clone())
                    .map_err(|e| anyhow::anyhow!("Failed to convert instrument to Python: {e}"))?;
                callable
                    .call1((py_instrument,))
                    .and_then(|result| result.extract::<bool>())
                    .map_err(|e| anyhow::anyhow!("filter_callable {filter_callable} failed: {e}"))
            })
        }

        #[cfg(not(feature = "python"))]
        {
            let _ = instrument;
            anyhow::bail!(
                "filter_callable {filter_callable:?} requires the Interactive Brokers adapter to be built with the python feature"
            );
        }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Install the module or add its directory to PYTHONPATH / sys.path
  2. Test 'python -c "import <module_name>"' in the same environment the trader runs in
  3. Fix any ImportError raised inside the target module (check the wrapped {e} message)
  4. Verify you are using the same venv/interpreter the nautilus node was launched with

Example fix

// before
filter_callable = "my_filters.skip_fx"  # my_filters not on sys.path
// after
// set PYTHONPATH=/path/to/project before launch, or
filter_callable = "my_project.filters.skip_fx"  # installed package
Defensive patterns

Strategy: try-catch

Validate before calling

import importlib
try:
    importlib.import_module(module_name)
except ImportError as e:
    raise RuntimeError(f"filter module {module_name} not importable: {e}")

Try / catch

try:
    run_with_filter(filter_callable)
except Exception as e:
    if "Failed to import" in str(e):
        print("check PYTHONPATH / install module:", e)
    else:
        raise

Prevention

When it happens

Trigger: filter_callable names a module that is not installed or not on sys.path (e.g. a custom module not present in the node's Python environment), or the module itself raises ImportError at import time.

Common situations: Running the trader from a different working directory so a local module isn't importable; custom filter module not added to the venv/PYTHONPATH; a typo in the module name; module imports a missing third-party package.

Related errors


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