risingwavelabs/risingwave · error · StreamExecutorError

ExchangeChannelClosed

Error message

ExchangeChannelClosed

What it means

The ExchangeChannelClosed variant transparently wraps exchange::error::ExchangeChannelClosed. It is thrown when the exchange layer's data channel between actors (the network path moving stream chunks/barriers between compute nodes) is found closed. It uses #[from] so any ExchangeChannelClosed propagates automatically into StreamExecutorError.

Source

Thrown at src/stream/src/executor/error.rs:88

    #[error("Sink error: sink_id={1}, error: {0}")]
    SinkError(
        #[source]
        #[backtrace]
        SinkError,
        SinkId,
    ),

    #[error(transparent)]
    RpcError(
        #[from]
        #[backtrace]
        RpcError,
    ),

    #[error("Channel closed: {0}")]
    ChannelClosed(String),

    #[error(transparent)]
    ExchangeChannelClosed(
        #[from]
        #[backtrace]
        ExchangeChannelClosed,
    ),

    #[error("Failed to align barrier: expected `{0:?}` but got `{1:?}`")]
    AlignBarrier(Box<Barrier>, Box<Barrier>),

    #[error("Connector error: {0}")]
    ConnectorError(
        #[source]
        #[backtrace]
        BoxedError,
    ),

    #[error(transparent)]
    DmlError(

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Inspect the wrapped ExchangeChannelClosed for which actor/channel closed.
  2. Check the remote compute node's logs for the original failure (crash, panic, graceful stop).
  3. Let the framework's failover restart affected actors and re-establish channels.
  4. If recurring, check network stability and node resource limits between compute nodes.
Defensive patterns

Strategy: try-catch

Validate before calling

// monitor exchange peer availability
if !actor_manager.is_actor_alive(peer_actor_id) {
    tracing::warn!("exchange peer actor {} not alive", peer_actor_id);
}

Type guard

fn is_exchange_closed(e: &StreamExecutorError) -> bool {
    e.variant_name() == "ExchangeChannelClosed"
}

Try / catch

match res {
    Err(e) if e.variant_name() == "ExchangeChannelClosed" => {
        // remote actor/node terminated; rely on actor restart/failover
    }
    other => other?,
}

Prevention

When it happens

Trigger: Produced by `?` on exchange send/recv operations in the exchange layer, wrapped here via From<ExchangeChannelClosed>. Happens when the remote endpoint of an inter-node/inter-actor exchange channel is closed.

Common situations: Remote compute node crashed or was killed; network disconnect during data exchange; actor terminated due to a fatal error upstream of the exchange.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/4bb7565489c3d463. Report an issue: GitHub.