risingwavelabs/risingwave · error · BatchError

Row sequential scan should not have input executor!

Error message

Row sequential scan should not have input executor!

What it means

SysRowSeqScanExecutorBuilder requires zero child executors. The system row sequential scan reads rows from a system (catalog/information-schema style) table and is a leaf plan node, so any input executor indicates the plan tree was built with an invalid child.

Source

Thrown at src/batch/executors/src/executor/sys_row_seq_scan.rs:60

    ) -> Self {
        Self {
            table_id,
            schema,
            column_indices,
            identity,
            sys_catalog_reader,
        }
    }
}

pub struct SysRowSeqScanExecutorBuilder {}

impl BoxedExecutorBuilder for SysRowSeqScanExecutorBuilder {
    async fn new_boxed_executor(
        source: &ExecutorBuilder<'_>,
        inputs: Vec<BoxedExecutor>,
    ) -> Result<BoxedExecutor> {
        ensure!(
            inputs.is_empty(),
            "Row sequential scan should not have input executor!"
        );
        let seq_scan_node = try_match_expand!(
            source.plan_node().get_node_body().unwrap(),
            NodeBody::SysRowSeqScan
        )?;
        let sys_catalog_reader = source.context().catalog_reader();

        let table_id = seq_scan_node.get_table_id();

        let column_indices = seq_scan_node
            .column_descs
            .iter()
            .map(|d| d.column_id as usize)
            .collect_vec();
        let schema = Schema::new(
            seq_scan_node

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Inspect the plan for the system-table query and confirm SysRowSeqScan is a leaf; fix the planner if it attaches children.
  2. Ensure frontend translation builds SysRowSeqScan with an empty children list.
  3. Pass an empty inputs vec when invoking this builder manually in tests.
  4. Report an internal bug with the query if the plan appears correct.

Example fix

// before
BatchPlanNode::new(NodeBody::SysRowSeqScan(node), vec![child])
// after
BatchPlanNode::new(NodeBody::SysRowSeqScan(node), vec![])
Defensive patterns

Strategy: try-catch

Validate before calling

// Rust: assert system-table scan is a leaf
assert!(inputs.is_empty(), "SysRowSeqScan must be a leaf node");

Type guard

fn is_leaf(inputs: &[BoxedExecutor]) -> bool { inputs.is_empty() }

Try / catch

if let Err(e) = exec.build(plan).await {
    if e.to_string().contains("should not have input executor") {
        // log the system-table query plan and file an internal bug
    }
}

Prevention

When it happens

Trigger: new_boxed_executor receives a non-empty `inputs` vector because a SysRowSeqScan plan node has children in the batch plan.

Common situations: Planner bugs attaching children to system-table scan nodes when planning queries against system catalogs; hand-assembled plan fragments in tests; refactors of node arity.

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


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