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
- Set `table.format-version = '3'` in the sink WITH options.
- Remove or cast the VARIANT column to a supported type (e.g. VARCHAR) if version 3 is unavailable.
- Verify the target catalog/storage supports Iceberg format v3 before upgrading.
- 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
- Always set table.format-version='3' when sinking JSONB/VARIANT columns.
- Confirm the target catalog/storage supports Iceberg format v3.
- Keep sink configs reviewed when adding VARIANT columns to source tables.
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
- invalid write_mode: {}, must be one of: {}, {}
- invalid compaction_type: {}, must be one of: {}, {}, {}, {}
- 'copy-on-write' mode is not supported for append-only iceber
- Invalid warehouse path: {}
- Partition source column does not exist in schema: {}
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/59fe3c2c4f3f75a0.
Report an issue: GitHub.