{"record":{"id":"8ffc17be017fa82f","repo":"risingwavelabs/risingwave","slug":"must-be-or-8ffc17","errorCode":null,"errorMessage":"`{}` must be {}, or {}","messagePattern":"`(.+?)` must be (.+?), or (.+?)","errorType":"validation","errorClass":"SinkError::Config","httpStatus":null,"severity":"error","filePath":"src/connector/src/sink/clickhouse.rs","lineNumber":385,"sourceCode":"\nimpl EnforceSecret for ClickHouseSink {\n    fn enforce_secret<'a>(\n        prop_iter: impl Iterator<Item = &'a str>,\n    ) -> crate::error::ConnectorResult<()> {\n        for prop in prop_iter {\n            ClickHouseConfig::enforce_one(prop)?;\n        }\n        Ok(())\n    }\n}\n\nimpl ClickHouseConfig {\n    pub fn from_btreemap(properties: BTreeMap<String, String>) -> Result<Self> {\n        let config =\n            serde_json::from_value::<ClickHouseConfig>(serde_json::to_value(properties).unwrap())\n                .map_err(|e| SinkError::Config(anyhow!(e)))?;\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        Ok(config)\n    }\n}\n\nimpl TryFrom<SinkParam> for ClickHouseSink {\n    type Error = SinkError;\n\n    fn try_from(param: SinkParam) -> std::result::Result<Self, Self::Error> {\n        let schema = param.schema();\n        let pk_indices = param.downstream_pk_or_empty();\n        let config = ClickHouseConfig::from_btreemap(param.properties)?;\n        Ok(Self {","sourceCodeStart":367,"sourceCodeEnd":403,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/sink/clickhouse.rs#L367-L403","documentation":"After parsing the ClickHouse sink config, from_btreemap validates that the `type` property is either 'append-only' or 'upsert'. Any other value (missing or misspelled) is rejected with this message naming the option and the two allowed values.","triggerScenarios":"ClickHouse CREATE SINK where the `type` property is absent or set to something other than SINK_TYPE_APPEND_ONLY ('append-only') or SINK_TYPE_UPSERT ('upsert').","commonSituations":"Typo like 'append_only' (underscore) or 'upsert-only', omitting `type` altogether, or copying `type` values valid for other connectors.","solutions":["Set type='append-only' for insert-only ClickHouse sinks.","Set type='upsert' for upsert sinks (also requires primary_key).","Check exact spelling/casing against the constants SINK_TYPE_APPEND_ONLY / SINK_TYPE_UPSERT."],"exampleFix":"// before\nWITH (connector='clickhouse', type='append_only', ...)\n// after\nWITH (connector='clickhouse', type='append-only', ...)","handlingStrategy":"validation","validationCode":"if (!['append-only', 'upsert'].includes(props.type)) throw new Error(`ClickHouse sink type must be 'append-only' or 'upsert', got: ${props.type}`);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use the exact hyphenated literals 'append-only' and 'upsert'.","Always set `type` explicitly for ClickHouse sinks.","Centralize sink DDL generation so type values come from a constant list."],"tags":["clickhouse","sink","config","required-field"],"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-14T16:17:12.679Z"}