risingwavelabs/risingwave · error · SinkError::Config

`enable_pk_index` is only supported for upsert iceberg sink

Error message

`enable_pk_index` is only supported for upsert iceberg sink

What it means

This error is raised during Iceberg sink configuration validation when `enable_pk_index = true` is set on a sink whose `type` is not `upsert`. The primary-key index feature only makes sense for upsert sinks, where a per-key index is needed to locate and overwrite rows; append-only sinks never update existing rows, so the option is rejected. Validation happens in `validate_enable_pk_index` (src/connector/src/sink/iceberg/config.rs:539), which is run when the sink config is built via `IcebergConfig::from_btreemap`.

Source

Thrown at src/connector/src/sink/iceberg/config.rs:545

        sink_type: &str,
        write_mode: IcebergWriteMode,
    ) -> Result<()> {
        if sink_type == SINK_TYPE_APPEND_ONLY && write_mode == IcebergWriteMode::CopyOnWrite {
            return Err(SinkError::Config(anyhow!(
                "'copy-on-write' mode is not supported for append-only iceberg sink. \
                 Please use 'merge-on-read' instead, which is strictly better for append-only workloads."
            )));
        }
        Ok(())
    }

    pub(crate) fn validate_enable_pk_index(&self) -> Result<()> {
        if !self.enable_pk_index {
            return Ok(());
        }

        if self.r#type != SINK_TYPE_UPSERT {
            return Err(SinkError::Config(anyhow!(
                "`enable_pk_index` is only supported for upsert iceberg sink"
            )));
        }

        if self.write_mode != IcebergWriteMode::MergeOnRead {
            return Err(SinkError::Config(anyhow!(
                "`enable_pk_index` is only supported for upsert iceberg sink with merge-on-read mode"
            )));
        }

        if self.format_version < FormatVersion::V2 {
            return Err(SinkError::Config(anyhow!(
                "`enable_pk_index` is only supported for upsert iceberg sink with format version >= 2"
            )));
        }

        if self.force_append_only {
            return Err(SinkError::Config(anyhow!(

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Remove `enable_pk_index = true` from the sink WITH options if the sink is append-only.
  2. Change the sink `type` to `'upsert'` (and provide a `primary-key` or keep `enable_pk_index`) if upsert semantics are intended.
  3. If only append-only output is needed, drop the pk-index feature entirely — it provides no benefit for append-only sinks.

Example fix

-- before
CREATE SINK s INTO iceberg_t WITH (
  connector = 'iceberg',
  type = 'append-only',
  enable_pk_index = true
);

-- after
CREATE SINK s INTO iceberg_t WITH (
  connector = 'iceberg',
  type = 'append-only'
);
Defensive patterns

Strategy: validation

Validate before calling

-- run before creating the sink
SELECT * FROM rw_catalog.rw_sinks WHERE name = 'my_sink';
-- ensure WITH options satisfy: type = 'upsert' whenever enable_pk_index = true

Try / catch

-- sink creation fails synchronously with a config error; fix the WITH clause and retry
CREATE SINK s INTO t WITH (connector='iceberg', type='upsert', enable_pk_index=true);

Prevention

When it happens

Trigger: Creating an Iceberg sink with WITH option `enable_pk_index = true` while `type = 'append-only'` (or any type other than 'upsert'). The check `self.r#type != SINK_TYPE_UPSERT` fails and `SinkError::Config` is returned before the sink is created.

Common situations: Copy-pasting a working upsert sink DDL and only changing the sink type to append-only while leaving `enable_pk_index` in the WITH clause; enabling the flag by habit on an append-only changelog sink; combining the flag with table-appender style sinks where it has no effect.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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