{"record":{"id":"8b5a603c61ad70dd","repo":"nautechsystems/nautilus_trader","slug":"simulation-module-module-index-method-failed","errorCode":null,"errorMessage":"Simulation module {module_index} {method} failed: {error:#}","messagePattern":"Simulation module (.+?) (.+?) failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/backtest/src/exchange.rs","lineNumber":349,"sourceCode":"            anyhow::bail!(\"Simulation module failure requires exchange reset: {error}\");\n        }\n        Ok(())\n    }\n\n    #[must_use]\n    pub(crate) const fn has_module_error(&self) -> bool {\n        self.module_error.is_some()\n    }\n\n    fn store_module_error(\n        &mut self,\n        module_index: usize,\n        method: &str,\n        error: &anyhow::Error,\n    ) -> anyhow::Error {\n        let error = format!(\"Simulation module {module_index} {method} failed: {error:#}\");\n        self.module_error = Some(error.clone());\n        anyhow::anyhow!(error)\n    }\n\n    fn pre_process_modules(&mut self, data: &Data) -> anyhow::Result<()> {\n        self.check_module_error()?;\n\n        for module_index in 0..self.modules.len() {\n            if let Err(e) = self.modules[module_index].pre_process(data) {\n                return Err(self.store_module_error(module_index, \"pre_process\", &e));\n            }\n        }\n        Ok(())\n    }\n\n    /// Returns the configured book type for this venue.\n    #[must_use]\n    pub const fn book_type(&self) -> BookType {\n        self.book_type\n    }","sourceCodeStart":331,"sourceCodeEnd":367,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/backtest/src/exchange.rs#L331-L367","documentation":"When a simulation module (aAct/act component attached to the exchange) raises an error during pre-processing or per-data processing, store_module_error wraps it with the module index and method name, stores it (the next module callback surfaces it via check_module_error), and returns the enriched error. It tells you exactly which module and phase failed.","triggerScenarios":"pre_process_modules or process_modules invoking module.pre_process(data)/module.process(data) (or similar) which returns Err for module at module_index; the wrapped message includes the original error chain via {error:#}.","commonSituations":"A custom user module panicking/erroring on unexpected data (None prices, missing instruments); a built-in module encountering data it cannot handle at the exchange level; module state corrupted after a prior failure.","solutions":["Read the full chained message (the suffix after 'failed:') for the module's root cause.","Inspect the module at the reported module_index (order of modules added to the exchange) and the reported method (pre_process vs process).","Harden your custom module's process/pre_process against missing instruments/prices by returning controlled errors or skipping.","Check the data stream for anomalies (gaps, zero prices) fed to the exchange before the module runs."],"exampleFix":"// before\nfn process(&mut self, data: &Data) -> anyhow::Result<()> {\n    let price = self.last_price(data.instrument_id()).unwrap(); // panics -> module error\n    Ok(())\n}\n// after\nfn process(&mut self, data: &Data) -> anyhow::Result<()> {\n    let Some(price) = self.last_price(data.instrument_id()) else {\n        tracing::warn!(\"no price yet for {}; skipping\", data.instrument_id());\n        return Ok(());\n    };\n    Ok(())\n}","handlingStrategy":"try-catch","validationCode":"// keep custom module processing defensive\nfn process(&mut self, data: &Data) -> anyhow::Result<()> {\n    self.state.required_context().ok_or_else(|| anyhow::anyhow!(\"module not initialized\"))?;\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if format!(\"{e:#}\").starts_with(\"Simulation module\") => {\n        // parse module_index and method from the message, log, then disable that module and retry\n        eprintln!(\"module failure: {e:#}\");\n    }\n    other => other?,\n}","preventionTips":["Make custom module methods total: handle missing instruments/prices gracefully instead of panicking.","Keep the module list small and log the index at registration so failures are traceable.","Test modules in isolation with representative data before attaching to a full backtest."],"tags":["rust","backtest","simulation-modules","error-wrapping"],"backgroundTag":"internal-invariant-violation","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}