risingwavelabs/risingwave · error · SinkError::Config

creating an Iceberg table with VARIANT column `{}` requires

Error message

creating an Iceberg table with VARIANT column `{}` requires `format_version = '3'`

What it means

RisingWave's VARIANT data type can only be stored in Iceberg tables using the Iceberg spec's Variant type, which requires format version 3. If the sink config specifies a lower table format version and any sink column contains a VARIANT type, creation is rejected with this configuration error before any catalog call.

Source

Thrown at src/connector/src/sink/iceberg/create_table.rs:123

    let namespace = table_id.namespace().clone();
    let table_name = table_id.name().to_owned();
    create_namespace_if_not_exists(catalog.as_ref(), &namespace).await?;

    if catalog
        .table_exists(&table_id)
        .await
        .map_err(|e| SinkError::Iceberg(anyhow!(e)))?
    {
        return Ok(false);
    }

    if config.table_format_version() < FormatVersion::V3
        && let Some(column) = param
            .columns
            .iter()
            .find(|column| column.data_type.contains_variant())
    {
        return Err(SinkError::Config(anyhow!(
            "creating an Iceberg table with VARIANT column `{}` requires `format_version = '3'`",
            column.name
        )));
    }

    let iceberg_create_table_arrow_convert = IcebergCreateTableArrowConvert::default();
    // convert risingwave schema -> arrow schema -> iceberg schema
    let arrow_fields = param
        .columns
        .iter()
        .map(|column| {
            Ok(iceberg_create_table_arrow_convert
                .to_arrow_field(&column.name, &column.data_type)
                .map_err(|e| SinkError::Iceberg(anyhow!(e)))
                .context(format!(
                    "failed to convert {}: {} to arrow type",
                    column.name, column.data_type
                ))?)

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Set `table.format-version = '3'` in the sink WITH options.
  2. Remove or cast the VARIANT column to a supported type (e.g. VARCHAR) if version 3 is unavailable.
  3. Verify the target catalog/storage supports Iceberg format v3 before upgrading.
  4. Recreate the sink after updating the config.

Example fix

// before
CREATE SINK s FROM mv WITH (connector='iceberg', table.format-version='2', ...);
// after
CREATE SINK s FROM mv WITH (connector='iceberg', table.format-version='3', ...);
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check: any VARIANT column requires format-version 3
let needs_v3 = param.columns.iter().any(|c| c.data_type.contains_variant());
if needs_v3 && config.table_format_version() < FormatVersion::V3 {
    eprintln!("set table.format-version = '3' for VARIANT columns");
}

Try / catch

match result {
    Err(SinkError::Config(e)) if e.to_string().contains("VARIANT") => {
        // recreate sink with table.format-version='3'
    }
    other => other?,
}

Prevention

When it happens

Trigger: create_table_if_not_exists_impl finds a column whose data_type contains_variant() while config.table_format_version() < FormatVersion::V3 — i.e. a VARIANT column in the sink plus missing or older `table.format-version` ('1' or '2').

Common situations: User sinks a table containing a JSONB/VARIANT column but leaves format-version at the default; copy-pasted sink config written before VARIANT support; older Iceberg REST catalogs that don't support v3 specs.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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