{"record":{"id":"d00a3f6a9a0266b8","repo":"risingwavelabs/risingwave","slug":"copy-on-write-mode-is-not-supported-for-append-o","errorCode":null,"errorMessage":"'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.","messagePattern":"'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\\.","errorType":"validation","errorClass":"SinkError::Config","httpStatus":null,"severity":"error","filePath":"src/connector/src/sink/iceberg/config.rs","lineNumber":531,"sourceCode":"            IcebergCommon::enforce_one(prop)?;\n        }\n        Ok(())\n    }\n\n    fn enforce_one(prop: &str) -> crate::error::ConnectorResult<()> {\n        IcebergCommon::enforce_one(prop)\n    }\n}\n\nimpl IcebergConfig {\n    /// Validate that append-only sinks use merge-on-read mode\n    /// Copy-on-write is strictly worse than merge-on-read for append-only workloads\n    pub fn validate_append_only_write_mode(\n        sink_type: &str,\n        write_mode: IcebergWriteMode,\n    ) -> Result<()> {\n        if sink_type == SINK_TYPE_APPEND_ONLY && write_mode == IcebergWriteMode::CopyOnWrite {\n            return Err(SinkError::Config(anyhow!(\n                \"'copy-on-write' mode is not supported for append-only iceberg sink. \\\n                 Please use 'merge-on-read' instead, which is strictly better for append-only workloads.\"\n            )));\n        }\n        Ok(())\n    }\n\n    pub(crate) fn validate_enable_pk_index(&self) -> Result<()> {\n        if !self.enable_pk_index {\n            return Ok(());\n        }\n\n        if self.r#type != SINK_TYPE_UPSERT {\n            return Err(SinkError::Config(anyhow!(\n                \"`enable_pk_index` is only supported for upsert iceberg sink\"\n            )));\n        }\n","sourceCodeStart":513,"sourceCodeEnd":549,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/sink/iceberg/config.rs#L513-L549","documentation":"The iceberg sink validates that an append-only sink (sink_type = 'append-only') never uses write_mode = 'copy-on-write'. Because copy-on-write offers no benefit for workloads that never update/delete existing rows, the library hard-rejects this combination and directs users to 'merge-on-read'. The check runs in validate_append_only_write_mode during sink creation.","triggerScenarios":"CREATE SINK ... WITH (connector='iceberg', sink_type='append-only' (or default append-only sink), write_mode='copy-on-write') — the combination is validated and rejected before the sink starts.","commonSituations":"Users copying write_mode settings from an upsert sink config; assuming copy-on-write is generally 'safer' or required for consistency; templates that set write_mode unconditionally regardless of sink_type.","solutions":["Change write_mode to 'merge-on-read' in the WITH clause","Remove the write_mode option so the default (merge-on-read) applies","If copy-on-write is genuinely required, create the sink without the append-only type (upsert-compatible setup) — though for append-only data this is unnecessary"],"exampleFix":"// before\nWITH (\n  connector = 'iceberg',\n  sink_type = 'append-only',\n  write_mode = 'copy-on-write'\n)\n// after\nWITH (\n  connector = 'iceberg',\n  sink_type = 'append-only',\n  write_mode = 'merge-on-read'\n)","handlingStrategy":"validation","validationCode":"fn validate_sink_options(sink_type: &str, write_mode: &str) -> Result<(), String> {\n    if sink_type == \"append-only\" && write_mode == \"copy-on-write\" {\n        return Err(\n            \"append-only sink cannot use copy-on-write; use merge-on-read\".to_string(),\n        );\n    }\n    Ok(())\n}","typeGuard":"fn is_invalid_append_only_combo(sink_type: &str, write_mode: IcebergWriteMode) -> bool {\n    sink_type == \"append-only\" && write_mode == IcebergWriteMode::CopyOnWrite\n}","tryCatchPattern":"match IcebergSinkConfig::validate_append_only_write_mode(sink_type, write_mode) {\n    Err(e) => {\n        // config conflict: switch write_mode to merge-on-read before creating the sink\n        return Err(e.context(\"set write_mode = 'merge-on-read' for append-only sinks\"));\n    }\n    Ok(()) => {}\n}","preventionTips":["Only set write_mode explicitly for upsert sinks; leave it unset for append-only sinks","Use merge-on-read by default — it is strictly better for append-only workloads","Keep separate config templates for append-only and upsert sink types","Validate the full WITH option set (sink_type x write_mode compatibility) before CREATE SINK"],"tags":["iceberg","config","validation","rust"],"backgroundTag":"conflicting-config-options","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}