{"record":{"id":"b063177a5dbbf98e","repo":"risingwavelabs/risingwave","slug":"enable-pk-index-cannot-be-true-when-force-appen","errorCode":null,"errorMessage":"`enable_pk_index` cannot be true when `force_append_only` is true","messagePattern":"`enable_pk_index` cannot be true when `force_append_only` is true","errorType":"validation","errorClass":"SinkError::Config","httpStatus":null,"severity":"error","filePath":"src/connector/src/sink/iceberg/config.rs","lineNumber":563,"sourceCode":"            return Err(SinkError::Config(anyhow!(\n                \"`enable_pk_index` is only supported for upsert iceberg sink\"\n            )));\n        }\n\n        if self.write_mode != IcebergWriteMode::MergeOnRead {\n            return Err(SinkError::Config(anyhow!(\n                \"`enable_pk_index` is only supported for upsert iceberg sink with merge-on-read mode\"\n            )));\n        }\n\n        if self.format_version < FormatVersion::V2 {\n            return Err(SinkError::Config(anyhow!(\n                \"`enable_pk_index` is only supported for upsert iceberg sink with format version >= 2\"\n            )));\n        }\n\n        if self.force_append_only {\n            return Err(SinkError::Config(anyhow!(\n                \"`enable_pk_index` cannot be true when `force_append_only` is true\"\n            )));\n        }\n\n        Ok(())\n    }\n\n    pub fn from_btreemap(values: BTreeMap<String, String>) -> Result<Self> {\n        let mut config =\n            serde_json::from_value::<IcebergConfig>(serde_json::to_value(&values).unwrap())\n                .map_err(|e| SinkError::Config(anyhow!(e)))?;\n\n        if config.enable_compaction && !values.contains_key(COMPACTION_MAX_SNAPSHOTS_NUM) {\n            config.max_snapshots_num_before_compaction = Some(DEFAULT_COMPACTION_MAX_SNAPSHOTS_NUM);\n        }\n\n        if config.r#type != SINK_TYPE_APPEND_ONLY && config.r#type != SINK_TYPE_UPSERT {\n            return Err(SinkError::Config(anyhow!(","sourceCodeStart":545,"sourceCodeEnd":581,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/sink/iceberg/config.rs#L545-L581","documentation":"This error is raised when both `enable_pk_index = true` and `force_append_only = true` are set on an Iceberg sink. `force_append_only` converts the sink to append-only output (no upserts/deletes), which directly contradicts the pk index's purpose of supporting key-based upserts; the combination is rejected in `validate_enable_pk_index` (src/connector/src/sink/iceberg/config.rs:562).","triggerScenarios":"Creating an Iceberg sink where the WITH options contain both `enable_pk_index = true` and `force_append_only = true`. Fails during `validate_enable_pk_index` regardless of sink type or write mode, because this is the last check in the chain.","commonSituations":"Users forcing append-only output from an upsert stream (e.g. to avoid delete files) while a pk-index flag from a previous template remains; combining feature flags without realizing they are mutually exclusive.","solutions":["Remove `force_append_only = true` if upsert semantics with the pk index are desired.","Or remove `enable_pk_index = true` if append-only output is truly what is needed — the index is meaningless there."],"exampleFix":"-- before\nWITH (\n  connector = 'iceberg',\n  type = 'upsert',\n  write_mode = 'merge-on-read',\n  format_version = 2,\n  force_append_only = true,\n  enable_pk_index = true\n);\n\n-- after\nWITH (\n  connector = 'iceberg',\n  type = 'upsert',\n  write_mode = 'merge-on-read',\n  format_version = 2,\n  enable_pk_index = true\n);","handlingStrategy":"validation","validationCode":"-- reject the combination before DDL:\n-- enable_pk_index = true AND force_append_only = true  -> invalid","typeGuard":null,"tryCatchPattern":"-- on error, decide which flag to drop: keep force_append_only OR enable_pk_index, never both","preventionTips":["Treat `enable_pk_index` and `force_append_only` as mutually exclusive options.","When templating, gate `enable_pk_index` behind upsert profiles only.","Read the validation chain in config.rs:539 to see the full set of constraints in order."],"tags":["iceberg","sink","mutually-exclusive","config-validation"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}