nautechsystems/nautilus_trader · error · anyhow::Error

Output channel not initialized

Error message

Output channel not initialized

What it means

create_connection() clones the pool's shared output sender (out_tx) to give the new connection a sink for parsed messages. This error means out_tx was None — the pool was constructed but its output channel was never initialized (or already taken/reset), so no connection can be created.

Source

Thrown at crates/adapters/binance/src/spot/websocket/public_json/client.rs:500

        let cache = instruments
            .iter()
            .map(|instrument| (instrument.raw_symbol().inner(), instrument.clone()))
            .collect();
        self.instruments_cache.store(cache);
    }

    /// Returns a shared reference to the instruments cache.
    #[must_use]
    pub fn instruments_cache(&self) -> Arc<AtomicMap<Ustr, InstrumentAny>> {
        self.instruments_cache.clone()
    }

    async fn create_connection(&self, slot_index: usize) -> anyhow::Result<ConnectionSlot> {
        let out_tx = self
            .out_tx
            .lock()
            .clone()
            .ok_or_else(|| anyhow::anyhow!("Output channel not initialized"))?;

        let (raw_handler, raw_rx) = channel_message_handler();
        let ping_handler: PingHandler = Arc::new(move |_| {});

        let config = WebSocketConfig {
            url: self.url.clone(),
            headers: vec![],
            heartbeat_interval_secs: self.heartbeat,
            heartbeat_payload: None,
            connect_timeout_ms: Some(5_000),
            reconnect_delay_initial_ms: Some(500),
            reconnect_delay_max_ms: Some(5_000),
            reconnect_backoff_factor: Some(2.0),
            reconnect_jitter_ms: Some(250),
            reconnect_max_attempts: None,
            heartbeat_timeout_secs: None,
            idle_timeout_ms: None,
            backend: self.transport_backend,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Initialize the client's output channel before connecting (use the constructor/factory that sets out_tx, e.g. the one taking the Messager/output sender).
  2. Verify initialization order: set up the output channel and message bus before any connect()/subscribe() call.
  3. Do not reuse a client after its output channel has been dropped/reset; build a fresh client.
  4. Check that the shutdown/reset path you run does not clear out_tx while connects are still expected.

Example fix

// before
let client = BinanceSpotPublicJsonWsClient::new(config); // out_tx never set
client.connect().await?; // Err: Output channel not initialized

// after
let client = BinanceSpotPublicJsonWsClient::new_with_output(config, out_tx); // set channel first
client.connect().await?;
Defensive patterns

Strategy: validation

Validate before calling

// ensure output channel is installed before any connect/subscribe
assert!(client.has_output_channel(), "out_tx must be initialized before connect");

Try / catch

match client.connect().await {
    Err(e) if e.to_string().contains("Output channel not initialized") => {
        anyhow::bail!("client misconfigured: initialize output channel before connecting");
    }
    r => r,
}

Prevention

When it happens

Trigger: Calling connect() or subscribe() (which call create_connection) on a client whose out_tx Option is None — typically a client created but never hooked to an output channel, or one whose output channel was cleared during shutdown/reset.

Common situations: Constructing the WS client manually without calling the initialization that installs out_tx; using a client after close/reset cleared the channel; wrong initialization order in custom wiring of the data engine.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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