risingwavelabs/risingwave · error

sink with auto schema change should have only 1 fragment, bu

Error message

sink with auto schema change should have only 1 fragment, but got {:?}

What it means

`check_sink_fragments_support_refresh_schema` verifies that a sink with automatic schema change (schema refresh) consists of exactly one fragment, since schema-evolution handling is only implemented for single-fragment sinks. If the generated sink job has multiple fragments, creation fails with the fragment count reported.

Source

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

fn clone_fragment(fragment: &Fragment, id_generator_manager: &IdGeneratorManager) -> Fragment {
    let fragment_id = GlobalFragmentIdGen::new(id_generator_manager, 1)
        .to_global_id(0)
        .as_global_id();
    Fragment {
        fragment_id,
        fragment_type_mask: fragment.fragment_type_mask,
        distribution_type: fragment.distribution_type,
        state_table_ids: fragment.state_table_ids.clone(),
        maybe_vnode_count: fragment.maybe_vnode_count,
        nodes: fragment.nodes.clone(),
    }
}

pub fn check_sink_fragments_support_refresh_schema(
    fragments: &BTreeMap<FragmentId, Fragment>,
) -> MetaResult<()> {
    if fragments.len() != 1 {
        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!(

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Disable auto schema change on the sink (` = false`) if multi-fragment topology is required.
  2. Simplify the sink definition so it plans into a single fragment (remove extra transformations between source and sink).
  3. Check the sink connector's plan generation for why multiple fragments are produced and use the supported single-fragment layout.

Example fix

// before
CREATE SINK s FROM mv WITH (connector = 'iceberg', auto_schema_change = true); -- plans to 2 fragments
// after
CREATE SINK s FROM mv WITH (connector = 'iceberg'); -- or ensure single-fragment plan with auto_schema_change = true
Defensive patterns

Strategy: validation

Validate before calling

-- SQL: check sink plan fragment count before enabling auto schema change
-- EXPLAIN CREATE SINK ... ; ensure a single sink fragment when auto_schema_change = true

Try / catch

// Rust: result of generate_streaming_job
match generate_streaming_job(...) {
    Ok(job) => job,
    Err(e) if e.to_string().contains("should have only 1 fragment") => {
        Err(anyhow!("disable auto schema change or simplify sink to one fragment: {e:#}"))
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Creating a sink with auto schema change enabled whose streaming job plans into more than one fragment (`check_sink_fragments_support_refresh_schema`, fragment.rs:401, called from `generate_streaming_job`).

Common situations: Sinks with complex downstream transformations (e.g. with extra operators forcing multiple fragments) combined with `auto_schema_change = true`; Iceberg sinks with connectors that split the plan into several fragments; older/newer frontend behavior differences around sink fragmentation.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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