risingwavelabs/risingwave · error

The stage has single distribution, but contains a source ope

Error message

The stage has single distribution, but contains a source operator

What it means

Raised while computing distribution/parallelism in the plan fragmenter (src/frontend/src/scheduler/plan_fragmenter.rs:1082): a stage whose plan has single (1-way) distribution was found to contain a source operator. Source operators require partitioned scheduling with splits, which contradicts the single-distribution assumption, so the invariant is broken.

Source

Thrown at src/frontend/src/scheduler/plan_fragmenter.rs:1082

                            tracing::warn!(
                                "The stage has single distribution, but contains a scan of table `{}` with {} partitions. A single random worker will be assigned",
                                info.name,
                                partitions.len()
                            );

                            *partitions = partitions
                                .drain()
                                .take(1)
                                .update(|(_, info)| {
                                    info.vnode_bitmap = Bitmap::ones(info.vnode_bitmap.len());
                                })
                                .collect();
                        }
                    } else {
                        // System table
                    }
                } else if source_info.is_some() {
                    return Err(SchedulerError::Internal(anyhow!(
                        "The stage has single distribution, but contains a source operator"
                    )));
                }
                1
            }
            _ => {
                if let Some(table_scan_info) = &table_scan_info {
                    table_scan_info
                        .partitions
                        .as_ref()
                        .map(|m| m.len())
                        .unwrap_or(1)
                } else if let Some(lookup_join_parallelism) =
                    self.collect_stage_lookup_join_parallelism(root.clone())?
                {
                    has_lookup_join = true;
                    lookup_join_parallelism
                } else if source_info.is_some() {

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Inspect `EXPLAIN (TRACE)` to find the source operator inside a single-distribution stage.
  2. Rewrite the query to avoid the pattern (e.g. add explicit ordering/limiting steps) as a workaround.
  3. Fix the optimizer rule so an exchange is inserted between a single-distribution consumer and a source scan.
  4. Report with the query and plan if it occurs on a stock workload.
Defensive patterns

Strategy: try-catch

Try / catch

match fragmenter_result {
    Err(e) if e.to_string().contains("single distribution, but contains a source operator") => {
        log::error!("plan invariant broken: source under single-distribution stage; check EXPLAIN (TRACE)");
    }
    r => r?,
}

Prevention

When it happens

Trigger: Fragmenting a batch plan where the optimizer emitted a single-distribution stage containing a source scan node — e.g. a source scan under an operator that forces single distribution (like certain aggregation or limit plans) without the expected exchange insertion.

Common situations: Internal planner/optimizer inconsistencies after plan-shape changes; queries with sources combined under single-distribution-forcing operators.

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/370be97dba34e568. Report an issue: GitHub.