nautechsystems/nautilus_trader · error · anyhow::Error
external message bus factory cannot be combined with injecte
Error message
external message bus factory cannot be combined with injected egress
What it means
NautilusKernelBuilder::build refuses a configuration that sets both an external message bus factory and injected external msgbus egress. These are two alternative mechanisms for integrating an external message bus, and combining them is ambiguous, so the builder fails fast at build time. It is a configuration-conflict check, not a runtime fault.
Source
Thrown at crates/system/src/builder.rs:337
/// Build and inject external message bus egress from a factory.
#[must_use]
pub fn with_external_msgbus_factory(
mut self,
factory: Box<dyn MessageBusBackingFactory>,
) -> Self {
self.external_msgbus_factory = Some(factory);
self
}
/// Build the [`NautilusKernel`] with the configured settings.
///
/// # Errors
///
/// Returns an error if kernel initialization fails.
pub fn build(self) -> anyhow::Result<NautilusKernel> {
if self.external_msgbus_factory.is_some() && self.external_msgbus_egress.is_some() {
anyhow::bail!("external message bus factory cannot be combined with injected egress");
}
if self.external_msgbus_factory.is_some()
&& self
.msgbus
.as_ref()
.and_then(|config| config.external_streams.as_ref())
.is_some_and(|streams| !streams.is_empty())
{
anyhow::bail!(
"NautilusKernelBuilder cannot consume external message bus streams; \
use LiveNodeBuilder::with_external_msgbus_factory for ingress"
);
}
let config = KernelConfig {
environment: self.environment,
trader_id: self.trader_id,View on GitHub (pinned to 18893faf8b)
Solutions
- Remove one of the two calls: keep the injected egress if you want direct message forwarding, or keep the factory if you want the external bus to be constructed by the factory
- Use LiveNodeBuilder::with_external_msgbus_factory instead if the external bus owns both ingress and egress
- Decide the integration style explicitly and set only the corresponding builder option
Example fix
// before
let kernel = NautilusKernelBuilder::new(config)
.with_external_msgbus_factory(factory)
.with_external_msgbus_egress(egress)
.build()?;
// after
let kernel = NautilusKernelBuilder::new(config)
.with_external_msgbus_egress(egress)
.build()?; Defensive patterns
Strategy: validation
Validate before calling
// Before build(): assert only one external-bus integration is configured
debug_assert!(
!(cfg.external_msgbus_factory.is_some() && cfg.external_msgbus_egress.is_some()),
"choose either external msgbus factory or injected egress, not both"
); Try / catch
match builder.build() {
Err(e) if e.to_string().contains("cannot be combined with injected egress") => {
// strip one of the two options and rebuild
}
other => other?,
} Prevention
- Pick one external-bus integration pattern per deployment and document it
- Centralize builder wiring in one constructor function
- Review builder chains for duplicated bus options during refactors
When it happens
Trigger: Calling NautilusKernelBuilder::with_external_msgbus_factory(...) and also providing external_msgbus_egress(...) on the same builder, then calling build().
Common situations: Copy-pasting wiring code from a LiveNodeBuilder example (which uses the factory) into a kernel builder that already injects egress; refactoring the bus integration and leaving both hooks set.
Related errors
- NautilusKernelBuilder cannot consume external message bus st
- default `PortfolioConfig` should be valid
- Invalid config type for AxExecutionClientFactory. Expected A
- Invalid factory address for DEX {name} on chain {chain} for
- heartbeat_secs must be positive when set
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/f98240759d6436d1.
Report an issue: GitHub.