risingwavelabs/risingwave · error · BatchError

Only support insert op in batch source executor

Error message

Only support insert op in batch source executor

What it means

convert_stream_chunk_to_batch_chunk converts chunks read by the batch source executor into batch DataChunks, and only INSERT operations are valid there. A batch query scanning a source expects append-only data; any Delete, UpdateInsert, or UpdateDelete op means the source produced non-append-only stream data and the executor bails out.

Solutions

  1. Ensure the queried source/table is append-only for batch reads, or filter out mutation records upstream.
  2. Use a materialized view over the source (which handles updates/deletes) and query the MV instead of the raw source in batch mode.
  3. If the connector is expected to be append-only, investigate why it emitted Delete/Update ops (e.g. CDC configuration emitting full row changes).
  4. Check that the stream chunk is compacted before conversion; call chunk.compact() upstream if needed.

Example fix

// before: batch query directly against CDC source emitting updates/deletes
SELECT * FROM cdc_source;
// after: query a materialized view that handles mutations
CREATE MATERIALIZED VIEW mv AS SELECT * FROM cdc_source;
SELECT * FROM mv;
Defensive patterns

Strategy: validation

Validate before calling

// Rust: check ops before converting
fn is_append_only(chunk: &StreamChunk) -> bool {
    chunk.ops().iter().all(|op| *op == Op::Insert)
}

Try / catch

match convert_stream_chunk_to_batch_chunk(chunk) {
    Ok(c) => /* consume */,
    Err(e) if e.to_string().contains("Only support insert op") => {
        // fallback: query a materialized view instead of the raw source
    }
}

Prevention

When it happens

Trigger: Batch source executor reads a StreamChunk whose ops contain anything other than Op::Insert — e.g. the underlying connector/table emits deletes or updates, or the chunk was not visibility-compacted (the preceding assert fails).

Common situations: Pointing a batch query at a source or table that can emit mutation records (CDC with deletes/updates) when the batch path only supports append-only reads; connector or stream-fragment bugs producing non-insert ops; version changes where batch source semantics changed.

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

Appendix: source

Thrown at src/batch/executors/src/executor/source.rs:184

        for event in stream {
            let chunk = match event.map_err(BatchError::connector)? {
                SourceReaderEvent::DataChunk(chunk) => chunk,
                SourceReaderEvent::SplitProgress(_) => continue,
            };
            let data_chunk = convert_stream_chunk_to_batch_chunk(chunk)?;
            if data_chunk.capacity() > 0 {
                yield data_chunk;
            }
        }
    }
}

fn convert_stream_chunk_to_batch_chunk(chunk: StreamChunk) -> Result<DataChunk> {
    // chunk read from source must be compact
    assert!(chunk.data_chunk().is_vis_compacted());

    if chunk.ops().iter().any(|op| *op != Op::Insert) {
        bail!("Only support insert op in batch source executor");
    }

    Ok(chunk.data_chunk().clone())
}

View on GitHub (pinned to 6469eb736d)