nautechsystems/nautilus_trader · error

Python SimulationModule.pre_process failed: {e}

Error message

Python SimulationModule.pre_process failed: {e}

What it means

A Python-side SimulationModule's pre_process method raised an exception while the backtest exchange pre-processed incoming data. The Rust wrapper converts the resulting PyErr into an anyhow error prefixed with this message.

Source

Thrown at crates/backtest/src/python/modules.rs:276

impl PythonSimulationModule {
    #[must_use]
    pub const fn new(obj: Py<PyAny>) -> Self {
        Self { obj }
    }

    pub(crate) fn clone_ref(&self, py: Python<'_>) -> Py<PyAny> {
        self.obj.clone_ref(py)
    }
}

impl SimulationModule for PythonSimulationModule {
    fn pre_process(&self, data: &Data) -> anyhow::Result<()> {
        Python::attach(|py| -> anyhow::Result<()> {
            let data = data_to_pyobject(py, data.clone())?;
            self.obj.bind(py).call_method1("pre_process", (data,))?;
            Ok(())
        })
        .map_err(|e| anyhow::anyhow!("Python SimulationModule.pre_process failed: {e}"))
    }

    fn process(
        &self,
        ts_now: nautilus_core::UnixNanos,
        ctx: &ExchangeContext,
    ) -> anyhow::Result<SimulationModuleResult> {
        Python::attach(|py| -> anyhow::Result<SimulationModuleResult> {
            let context = Py::new(py, PySimulationModuleContext::from_exchange(ctx))?;
            let adjustments = self
                .obj
                .bind(py)
                .call_method1("process", (ts_now.as_u64(), context))?
                .extract::<Option<Vec<Money>>>()?;
            Ok(adjustments.map_or(
                SimulationModuleResult::NotReady,
                SimulationModuleResult::Completed,
            ))

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Read the chained Python traceback in the error text and fix the exception in the Python module's pre_process method.
  2. Add defensive handling for the data types your module can receive (use isinstance checks on the converted data object).
  3. Test the module in isolation by calling pre_process with sample data before running the full backtest.

Example fix

# before
def pre_process(self, data):
    return self.state[data.venue]  # KeyError propagates
# after
def pre_process(self, data):
    return self.state.get(data.venue, None)
Defensive patterns

Strategy: try-catch

Validate before calling

module.pre_process(sample_data)  # smoke-test with representative data before the backtest

Try / catch

class SafeModule(SimulationModule):
    def pre_process(self, data):
        try:
            return self._pre_process(data)
        except Exception:
            logging.exception("SimulationModule.pre_process failed")
            raise

Prevention

When it happens

Trigger: The Python object implementing SimulationModule.pre_process(data) raises any exception during the backtest data pipeline (buggy user code, bad data conversion, wrong data type handling in the module).

Common situations: User-authored simulation module assumptions broken by the data payload type; None handling errors; unhandled market-data formats in custom fill models or fee modules.

Related errors


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