nautechsystems/nautilus_trader · error · anyhow::Error

external ingress receiver unavailable

Error message

external ingress receiver unavailable

What it means

MessageBusBacking's default take_receiver implementation always fails: the base trait provides no receiver, so attempting to take the external ingress receiver on a backing that does not supply one yields this error. Concrete backings that own a receiver override this method; the default exists so implementations without an external receiver compile.

Source

Thrown at crates/common/src/msgbus/backing.rs:83

///
/// Implementations own the concrete backing technology and provide the runtime-facing publication
/// surface used by the core bus. With the `live` feature, the same backing can also hand an
/// inbound receiver to the live bridge.
pub trait MessageBusBacking {
    /// Returns `true` if the backing has been closed.
    fn is_closed(&self) -> bool;

    /// Queues a serialized bus message for external egress.
    fn publish(&self, message: BusMessage);

    /// Takes the inbound message receiver for live bridge consumption.
    ///
    /// # Errors
    ///
    /// Returns an error if the receiver has already been taken or is unavailable.
    #[cfg(feature = "live")]
    fn take_receiver(&mut self) -> anyhow::Result<MessageBusExternalReceiver> {
        anyhow::bail!("external ingress receiver unavailable")
    }

    /// Closes the backing and releases any owned resources.
    fn close(&mut self);
}

/// External egress surface for serialized message bus publications.
///
/// The core bus passes each outbound message as a [`BusMessage`] carrying the
/// `topic`, `payload_type`, and serialized `payload`. Implementations must not block the publishing
/// thread. If the underlying channel is full, drop the message in the implementation rather than
/// applying back-pressure to the node.
pub trait MessageBusExternalEgress {
    /// Returns `true` if egress has been closed.
    fn is_closed(&self) -> bool;

    /// Queues a serialized bus message for external egress.
    fn publish(&self, message: BusMessage);

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Only call take_receiver when the bus was constructed with external ingress backing (live feature, external sender configured).
  2. Call take_receiver exactly once and store the returned receiver; repeated calls fail.
  3. Check which concrete backing type you created; use a backing implementation that owns and yields a receiver if you need external ingress.
  4. Handle the error gracefully: fall back to internal-only message routing when no external receiver is present.

Example fix

// before
let rx = backing.take_receiver()?; // bails on default backing
// after
match backing.take_receiver() {
    Ok(rx) => { /* wire external sender */ }
    Err(_) => { /* no external ingress; run internal-only bus */ }
}
Defensive patterns

Strategy: fallback

Try / catch

match backing.take_receiver() {
    Ok(rx) => start_external_ingress(rx),
    Err(e) if e.to_string().contains("receiver unavailable") => run_internal_only_bus(),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling take_receiver on a MessageBusBacking instance that uses the default implementation (no external ingress configured), typically when wiring external senders to the message bus in live mode.

Common situations: Live-node setup code that assumes every bus backing exposes an external receiver, or calling take_receiver twice — the first call consumes the receiver and later calls on a non-refundable implementation effectively become unavailable.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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