risingwavelabs/risingwave · error

the upstream fragment should be a MView or Source, got fragm

Error message

the upstream fragment should be a MView or Source, got fragment type: {:b}

What it means

When building the stream graph, downstream edges can only connect to an upstream fragment of type MView (materialized view) or Source without an explicit dispatcher being constructed. If the upstream fragment's type mask is anything else, the builder bails with this error. It prevents connecting a dispatcher-based edge to an upstream fragment that cannot serve as such an upstream.

Source

Thrown at src/meta/src/stream/stream_graph/fragment.rs:1878

                                        "BUG: column not found in the upstream source node",
                                    )?
                                };

                                StreamFragmentEdge {
                                    id: EdgeId::UpstreamExternal {
                                        upstream_job_id,
                                        downstream_fragment_id: id,
                                    },
                                    // We always use `NoShuffle` for the exchange between the upstream
                                    // `Source` and the downstream `StreamScan` of the new MV.
                                    dispatch_strategy: DispatchStrategy {
                                        r#type: DispatcherType::NoShuffle as _,
                                        dist_key_indices: vec![], // not used for `NoShuffle`
                                        output_mapping: Some(output_mapping),
                                    },
                                }
                            } else {
                                bail!(
                                    "the upstream fragment should be a MView or Source, got fragment type: {:b}",
                                    upstream_fragment.fragment_type_mask
                                )
                            }
                        }
                        StreamingJobType::Source | StreamingJobType::Table(_) => {
                            bail!(
                                "the streaming job shouldn't have an upstream fragment, job_type: {:?}",
                                job_type
                            )
                        }
                    };

                    // put the edge into the extra edges
                    extra_downstreams
                        .entry(upstream_root_fragment_id)
                        .or_insert_with(HashMap::new)
                        .try_insert(id, edge.clone())

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Check the SQL: ensure the upstream object is a materialized view or source; create an MV on top of the table if needed and build from that.
  2. Inspect `upstream_fragment.fragment_type_mask` and confirm the intended upstream; if the planner should have rewritten it, check the frontend plan for missing rewriting.
  3. Update RisingWave or file a bug with the DDL statement if a normal MV/Source upstream still triggers this.

Example fix

-- before: CREATE MATERIALIZED VIEW mv2 AS SELECT * FROM base_table;  (upstream is a Table materialize fragment)
-- after: create an MV over it first
CREATE MATERIALIZED VIEW mv1 AS SELECT * FROM base_table;
CREATE MATERIALIZED VIEW mv2 AS SELECT * FROM mv1;
Defensive patterns

Strategy: validation

Validate before calling

let ok = upstream_fragment.fragment_type_mask == (FragmentTypeMask::MView as u32)
    || upstream_fragment.fragment_type_mask == (FragmentTypeMask::Source as u32);
if !ok { return Err("upstream must be MView or Source"); }

Type guard

fn is_mview_or_source(mask: u32) -> bool {
    mask == FragmentTypeMask::MView as u32 || mask == FragmentTypeMask::Source as u32
}

Try / catch

match build_stream_graph(job) {
    Err(e) if e.to_string().contains("upstream fragment should be a MView or Source") => {
        // fall back: create an MV over the upstream table first
    }
    other => other?,
}

Prevention

When it happens

Trigger: Creating a streaming job whose external upstream fragment has a fragment type other than MView or Source (e.g. a Table/ materialize fragment or any other mask) while the builder takes the NoShuffle-dispatcher path in graph building.

Common situations: Creating a table/sink whose upstream is another table's materialize fragment in a way the planner did not rewrite into a proper MV chain; version changes or planner bugs that leave an unexpected upstream fragment type.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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