risingwavelabs/risingwave · error · BatchError
MergeSortExchangeExecutor should not have child!
Error message
MergeSortExchangeExecutor should not have child!
What it means
`MergeSortExchangeExecutorBuilder::new_boxed_executor` requires that a MergeSortExchange plan node has no child executors; the merge-sort exchange pulls its inputs from remote exchange sources rather than a local child. A non-empty `inputs` vector means the executor tree is structurally invalid, so plan construction fails with this message (which says "should not have child").
Source
Thrown at src/batch/executors/src/executor/merge_sort_exchange.rs:131
self.chunk_size,
self.mem_ctx,
));
#[for_await]
for chunk in merge_sort_executor.execute() {
yield chunk?;
}
}
}
pub struct MergeSortExchangeExecutorBuilder {}
impl BoxedExecutorBuilder for MergeSortExchangeExecutorBuilder {
async fn new_boxed_executor(
source: &ExecutorBuilder<'_>,
inputs: Vec<BoxedExecutor>,
) -> Result<BoxedExecutor> {
ensure!(
inputs.is_empty(),
"MergeSortExchangeExecutor should not have child!"
);
let sort_merge_node = try_match_expand!(
source.plan_node().get_node_body().unwrap(),
NodeBody::MergeSortExchange
)?;
let column_orders = sort_merge_node
.column_orders
.iter()
.map(ColumnOrder::from_protobuf)
.collect();
let column_orders = Arc::new(column_orders);
let exchange_node = sort_merge_node.get_exchange()?;
let proto_sources: Vec<PbExchangeSource> = exchange_node.get_sources().clone();
let source_creators =View on GitHub (pinned to 6469eb736d)
Solutions
- Verify the distributed plan: MergeSortExchange must have no local child; its receiver should be a separate MergeSortExchangeReceiver node.
- Upgrade meta and compute nodes to matching versions to rule out plan-format skew.
- If reproducible from a normal query, capture the fragment and file a RisingWave issue with the EXPLAIN output.
Defensive patterns
Strategy: validation
Validate before calling
// validate plan shape before dispatching the fragment
fn assert_exchange_shape(node: &PlanNode) -> Result<()> {
if matches!(node.node_body, Some(NodeBody::MergeSortExchange(_))) {
ensure!(node.children.is_empty(), "MergeSortExchange must not have a local child");
}
Ok(())
} Prevention
- Treat distributed plan fragments as meta-owned; never hand-assemble exchange trees.
- Keep meta and compute versions in sync.
- Add fragment-structure assertions in distributed-plan tests.
When it happens
Trigger: Building a batch executor tree where a `MergeSortExchange` NodeBody has a child attached in the plan fragment — i.e. malformed plan distribution where the node should sit above a MergeSortExchangeReceiver but was given local input.
Common situations: Version skew or bugs in meta's plan distribution placing the node incorrectly; hand-crafted plan fragments in tests; corrupted exchange wiring after scheduler changes.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- LogStore row sequential scan should not have input executor!
- Row sequential scan should not have input executor!
- Source should not have input executor!
- Row sequential scan should not have input executor!
- ValuesExecutor should have no child!
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/80f916010ca7159e.
Report an issue: GitHub.