{"record":{"id":"d2960c8e47d9a07f","repo":"risingwavelabs/risingwave","slug":"must-be-or-d2960c","errorCode":null,"errorMessage":"`{}` must be {}, or {}","messagePattern":"`(.+?)` must be (.+?), or (.+?)","errorType":"validation","errorClass":"SinkError::Config","httpStatus":null,"severity":"error","filePath":"src/connector/src/sink/iceberg/config.rs","lineNumber":581,"sourceCode":"            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!(\n                \"`{}` must be {}, or {}\",\n                SINK_TYPE_OPTION,\n                SINK_TYPE_APPEND_ONLY,\n                SINK_TYPE_UPSERT\n            )));\n        }\n\n        if config.r#type == SINK_TYPE_UPSERT {\n            if let Some(primary_key) = &config.primary_key {\n                if primary_key.is_empty() {\n                    return Err(SinkError::Config(anyhow!(\n                        \"`primary-key` must not be empty in {}\",\n                        SINK_TYPE_UPSERT\n                    )));\n                }\n            } else if !config.enable_pk_index {\n                // When `enable_pk_index = true`, the planner auto-derives the iceberg pk\n                // from the upstream stream key, so the user does not need to spell it out","sourceCodeStart":563,"sourceCodeEnd":599,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/sink/iceberg/config.rs#L563-L599","documentation":"This error is raised by `IcebergConfig::from_btreemap` (src/connector/src/sink/iceberg/config.rs:580) when the `type` sink option is neither `'append-only'` nor `'upsert'`. The Iceberg sink supports exactly these two write types; any other value (including typos and empty strings) is rejected with `SinkError::Config` naming the option and the two allowed values.","triggerScenarios":"Creating an Iceberg sink with `type` set to any value other than 'append-only' or 'upsert' — e.g. `type = 'upsert'` misspelled as 'upsert-only'/'Upsert' (values are compared case-sensitively), `type = ''`, or a type copied from a different connector (e.g. 'append_only' with an underscore).","commonSituations":"Typo in the WITH clause; copying `type` values from other sink connectors with different vocabularies; case mismatch ('UPSERT' vs 'upsert'); omitting the value's quotes so an unexpected literal lands in the map.","solutions":["Set `type = 'append-only'` or `type = 'upsert'` (exact lowercase spelling) in the sink WITH options.","Remove the `type` option entirely if the default is acceptable and no custom value is needed.","Check the exact string against SINK_TYPE_APPEND_ONLY / SINK_TYPE_UPSERT constants — values are matched case-sensitively, no normalization is applied."],"exampleFix":"-- before\nWITH (\n  connector = 'iceberg',\n  type = 'UPSERT'\n);\n\n-- after\nWITH (\n  connector = 'iceberg',\n  type = 'upsert'\n);","handlingStrategy":"validation","validationCode":"-- allowed values for the iceberg sink type option:\n-- type in ('append-only', 'upsert')  -- exact, lowercase, no underscores","typeGuard":null,"tryCatchPattern":"-- SinkError::Config at CREATE SINK time; fix `type` to one of the listed values and retry","preventionTips":["Copy type values only from RisingWave Iceberg sink docs, not other connectors.","Use exact lowercase literals; no case normalization is applied.","Let the option default when no custom behavior is needed."],"tags":["iceberg","sink","invalid-enum-value","config-validation"],"backgroundTag":"invalid-enum-value","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"}