risingwavelabs/risingwave · error
VARIANT column `{}` cannot be used as the primary key of an
Error message
VARIANT column `{}` cannot be used as the primary key of an upsert iceberg sink What it means
For upsert (primary-key) Iceberg sinks, the primary key columns must be stored as Iceberg identity fields, but Iceberg does not support VARIANT (semi-structured) columns as identity/primary-key fields. Validation therefore rejects any sink whose PK includes a column containing a VARIANT type.
Source
Thrown at src/connector/src/sink/iceberg/mod.rs:260
self.config.write_mode,
)?;
validate_explicit_compaction_type(&self.config)?;
validate_compaction_option_compatibility(&self.config)?;
// VARIANT is not comparable, so it can never be an equality-delete key.
if self.config.r#type == SINK_TYPE_UPSERT
&& !self.config.force_append_only
&& let Some(pk_indices) = self
.param
.downstream_pk
.as_ref()
.filter(|pk| !pk.is_empty())
{
for &idx in pk_indices {
if let Some(column) = self.param.columns.get(idx)
&& column.data_type.contains_variant()
{
bail!(
"VARIANT column `{}` cannot be used as the primary key of an upsert iceberg sink",
column.name
);
}
}
}
let table = self.create_and_validate_table().await?;
self.config
.validate_manifest_rewrite_format(table.metadata().format_version())?;
Ok(())
}
fn support_schema_change() -> bool {
true
}
fn validate_alter_config_change(View on GitHub (pinned to 6469eb736d)
Solutions
- Choose a primary key made of non-variant columns (integers, strings, timestamps, etc.).
- Extract the key into a concrete typed column in the MV and use it as the sink PK.
- Change the sink to an append-only sink (no primary key) if upsert semantics are not required.
Example fix
-- before CREATE SINK s FROM mv WITH (connector='iceberg', primary_key='payload'); -- payload is jsonb -- after CREATE SINK s FROM mv WITH (connector='iceberg', primary_key='id'); -- id is BIGINT
Defensive patterns
Strategy: validation
Validate before calling
-- ensure no PK column is jsonb/variant
SELECT c.name
FROM rw_columns c
WHERE c.relation_id = <sink_upstream_mv_id>
AND c.name = ANY(ARRAY[<pk_columns>])
AND c.data_type IN ('jsonb', 'variant'); Prevention
- Never use jsonb/variant columns as primary keys in upsert sinks.
- Model dedup keys as concrete typed columns in the upstream MV.
- Prefer append-only sinks when no true key exists.
When it happens
Trigger: Creating an upsert Iceberg sink whose primary key includes a `jsonb`/VARIANT column, including via nested `contains_variant()` types (e.g. struct fields containing variant).
Common situations: Streaming CDC tables where the natural key was modeled as jsonb; users materializing a deduplicated table keyed on a variant payload instead of concrete key columns.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- primary key must be specified for upsert iceberg sink
- Primary key not defined for upsert clickhouse sink (please d
- `primary-key` must not be empty in {}
- Must set `primary-key` in {}
- primary key column index {} out of range in sink schema
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/e97c9b84357dcd13.
Report an issue: GitHub.