risingwavelabs/risingwave · error

Project node must have exactly 1 input for auto schema chang

Error message

Project node must have exactly 1 input for auto schema change, but got {:?}

What it means

When the sink fragment's node under the sink is a Project (used for auto schema change), the code expects that Project to have exactly one input (the StreamScan). If the Project node has any other number of inputs, this error is returned. The message misleadingly formats `stream_input_node.input.len()` with `{:?}`.

Source

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

        return Err(anyhow!(
            "sink with auto schema change should have only 1 fragment, but got {:?}",
            fragments.len()
        )
        .into());
    }
    let (_, fragment) = fragments.first_key_value().expect("non-empty");
    let sink_node = &fragment.nodes;
    let PbNodeBody::Sink(_) = sink_node.node_body.as_ref().unwrap() else {
        return Err(anyhow!("expect PbNodeBody::Sink but got: {:?}", sink_node.node_body).into());
    };
    let [stream_input_node] = sink_node.input.as_slice() else {
        panic!("Sink has more than 1 input: {:?}", sink_node.input);
    };
    let stream_scan_node = match stream_input_node.node_body.as_ref().unwrap() {
        PbNodeBody::StreamScan(_) => stream_input_node,
        PbNodeBody::Project(_) => {
            let [stream_scan_node] = stream_input_node.input.as_slice() else {
                return Err(anyhow!(
                    "Project node must have exactly 1 input for auto schema change, but got {:?}",
                    stream_input_node.input.len()
                )
                .into());
            };
            stream_scan_node
        }
        _ => {
            return Err(anyhow!(
                "expect PbNodeBody::StreamScan or PbNodeBody::Project but got: {:?}",
                stream_input_node.node_body
            )
            .into());
        }
    };
    let PbNodeBody::StreamScan(scan) = stream_scan_node.node_body.as_ref().unwrap() else {
        return Err(anyhow!(
            "expect PbNodeBody::StreamScan but got: {:?}",

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Confirm the sink was created with schema refresh supported (single-arrangement-backfill source); recreate the sink if its graph was built by an older planner.
  2. Check frontend and meta versions match; redeploy with aligned binaries.
  3. Inspect the fragment graph in meta logs to see the actual input count of the project node.
  4. Report to RisingWave if a supported `CREATE SINK` triggers it.

Example fix

// before
let [stream_scan_node] = stream_input_node.input.as_slice() else { ... };
// after: handle the shape explicitly upstream
if stream_input_node.input.len() != 1 {
    return Err(anyhow!("unexpected project fan-in {} for schema refresh", stream_input_node.input.len()).into());
}
let [stream_scan_node] = stream_input_node.input.as_slice() else { unreachable!() };
Defensive patterns

Strategy: validation

Validate before calling

if let Some(PbNodeBody::Project(_)) = stream_input_node.node_body.as_ref() {
    assert_eq!(stream_input_node.input.len(), 1, "project fan-in must be 1");
}

Type guard

fn is_single_input_project(node: &StreamNode) -> Option<&StreamNode> {
    match (node.node_body.as_ref(), node.input.as_slice()) {
        (Some(PbNodeBody::Project(_)), [only]) => Some(only),
        _ => None,
    }
}

Prevention

When it happens

Trigger: `generate_streaming_job` -> `check_sink_fragments_support_refresh_schema` encountering a `PbNodeBody::Project` node between the sink and the stream scan whose `input` slice is not exactly length 1 (0 or 2+ inputs).

Common situations: Auto schema change (schema registry evolution, e.g. adding/removing columns on a table being backfilled into a sink) producing an unexpected multi-input project; corrupted or hand-edited fragment metadata; frontend/meta version mismatch.

Related errors


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