{"record":{"id":"fe2b2f1714594b4f","repo":"nautechsystems/nautilus_trader","slug":"nautiluskernelbuilder-cannot-consume-external-mess","errorCode":null,"errorMessage":"NautilusKernelBuilder cannot consume external message bus streams; use LiveNodeBuilder::with_external_msgbus_factory for ingress","messagePattern":"NautilusKernelBuilder cannot consume external message bus streams; use LiveNodeBuilder::with_external_msgbus_factory for ingress","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/system/src/builder.rs","lineNumber":347,"sourceCode":"\n    /// Build the [`NautilusKernel`] with the configured settings.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if kernel initialization fails.\n    pub fn build(self) -> anyhow::Result<NautilusKernel> {\n        if self.external_msgbus_factory.is_some() && self.external_msgbus_egress.is_some() {\n            anyhow::bail!(\"external message bus factory cannot be combined with injected egress\");\n        }\n\n        if self.external_msgbus_factory.is_some()\n            && self\n                .msgbus\n                .as_ref()\n                .and_then(|config| config.external_streams.as_ref())\n                .is_some_and(|streams| !streams.is_empty())\n        {\n            anyhow::bail!(\n                \"NautilusKernelBuilder cannot consume external message bus streams; \\\n                 use LiveNodeBuilder::with_external_msgbus_factory for ingress\"\n            );\n        }\n\n        let config = KernelConfig {\n            environment: self.environment,\n            trader_id: self.trader_id,\n            load_state: self.load_state,\n            save_state: self.save_state,\n            shutdown_on_error: self.shutdown_on_error,\n            logging: self.logging.unwrap_or_default(),\n            instance_id: self.instance_id,\n            timeout_connection: self.timeout_connection,\n            timeout_reconciliation: self.timeout_reconciliation,\n            timeout_portfolio: self.timeout_portfolio,\n            timeout_disconnection: self.timeout_disconnection,\n            delay_post_stop: self.delay_post_stop,","sourceCodeStart":329,"sourceCodeEnd":365,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/system/src/builder.rs#L329-L365","documentation":"NautilusKernelBuilder::build rejects a MessageBus configuration that declares external_streams, because only LiveNodeBuilder (with an external msgbus factory) can consume streams from an external bus process. The plain kernel builder has no ingress machinery, so the configuration would silently do nothing; it bails instead. This is a static configuration validation.","triggerScenarios":"Building a kernel whose MessageBusConfig.external_streams is a non-empty list while using NautilusKernelBuilder::build() rather than LiveNodeBuilder::with_external_msgbus_factory(...).","commonSituations":"Porting a live-node config (with Redis/external bus streams) to an offline or backtest kernel builder; enabling external streams in shared config used by both kernel and node creation paths.","solutions":["Remove external_streams from MessageBusConfig when building with NautilusKernelBuilder","Switch to LiveNodeBuilder and call with_external_msgbus_factory(...) to get stream ingress","Split the config: keep external_streams only in the live-node configuration path"],"exampleFix":"// before\nlet config = KernelConfig { msgbus: MessageBusConfig { external_streams: Some(vec![\"ticks\".into()]), ..Default::default() }, .. };\nlet kernel = NautilusKernelBuilder::new(config).build()?;\n// after: live node path\nlet node = LiveNodeBuilder::new(core_config)\n    .with_external_msgbus_factory(factory)\n    .build()?;","handlingStrategy":"validation","validationCode":"// Guard before building with NautilusKernelBuilder\nlet uses_streams = kernel_config\n    .msgbus\n    .as_ref()\n    .and_then(|m| m.external_streams.as_ref())\n    .is_some_and(|s| !s.is_empty());\ndebug_assert!(!uses_streams, \"external_streams require LiveNodeBuilder\");","typeGuard":null,"tryCatchPattern":"match builder.build() {\n    Err(e) if e.to_string().contains(\"cannot consume external message bus streams\") => {\n        // fall back to LiveNodeBuilder::with_external_msgbus_factory\n    }\n    other => other?,\n}","preventionTips":["Keep external_streams only in live-node configs","Validate the config type matches the builder being used","Use LiveNodeBuilder for any config involving an external message bus"],"tags":["rust","builder","message-bus","config","live-node"],"backgroundTag":"unsupported-operation","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}