{"record":{"id":"86770e88d7b0cda6","repo":"risingwavelabs/risingwave","slug":"must-be-or-86770e","errorCode":null,"errorMessage":"`{}` must be {}, or {}","messagePattern":"`(.+?)` must be (.+?), or (.+?)","errorType":"validation","errorClass":"SinkError","httpStatus":null,"severity":"error","filePath":"src/connector/src/sink/file_sink/gcs.rs","lineNumber":100,"sourceCode":"            .layer(LoggingLayer::default())\n            .layer(RetryLayer::default());\n        Ok(operator)\n    }\n}\n\n#[derive(Debug, Clone, Copy, PartialEq, Eq)]\npub struct GcsSink;\n\nimpl OpendalSinkBackend for GcsSink {\n    type Properties = GcsConfig;\n\n    const SINK_NAME: &'static str = GCS_SINK;\n\n    fn from_btreemap(btree_map: BTreeMap<String, String>) -> Result<Self::Properties> {\n        let config = serde_json::from_value::<GcsConfig>(serde_json::to_value(btree_map).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    fn new_operator(properties: GcsConfig) -> Result<Operator> {\n        FileSink::<GcsSink>::new_gcs_sink(properties)\n    }\n\n    fn get_path(properties: Self::Properties) -> String {\n        properties.common.path\n    }\n\n    fn get_engine_type() -> super::opendal_sink::EngineType {","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/sink/file_sink/gcs.rs#L82-L118","documentation":"This error is thrown when creating a GCS file sink whose `type` property is neither 'append-only' nor 'upsert'. The sink connector validates the user-provided `sink.type` option against the two supported sink types and rejects anything else with a SinkError::Config. It is a fail-fast validation in `from_btreemap` before the sink is ever instantiated.","triggerScenarios":"Creating a GCS sink where the WITH option `type` is set to an unsupported value (e.g. `type = 'debezium'`, `type = 'append'`, misspelled 'append-only'), or where `type` deserializes into a GcsConfig with an unexpected string.","commonSituations":"Typo in the sink type option; copying config from a non-file sink connector that uses other type values; assuming the option name is something other than `type` and a stale/empty value is parsed.","solutions":["Set the WITH option to a supported value: `type = 'append-only'` or `type = 'upsert'`","Check for typos in the value (exact strings 'append-only' and 'upsert')","If upsert semantics are needed with a file sink, note file sinks require append-only output, so prefer `type = 'append-only'` combined with `force_append_only = 'true'` on the encode"],"exampleFix":"// before\nWITH (\n  connector = 'gcs',\n  type = 'append'\n)\n// after\nWITH (\n  connector = 'gcs',\n  type = 'append-only'\n)","handlingStrategy":"validation","validationCode":"let supported = [\"append-only\", \"upsert\"];\nlet sink_type = props.get(\"type\").map(|s| s.as_str()).unwrap_or(\"\");\nif !supported.contains(&sink_type) {\n    return Err(format!(\"GCS sink requires type to be one of {:?}, got '{}'\", supported, sink_type));\n}","typeGuard":"fn is_valid_sink_type(v: &str) -> bool {\n    matches!(v, \"append-only\" | \"upsert\")\n}","tryCatchPattern":null,"preventionTips":["Always specify `type` explicitly in the WITH clause for GCS file sinks","Keep sink definitions in version-controlled SQL files with supported values only","Check the connector's supported sink types in docs before copying configs from other connectors"],"tags":["sink","gcs","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-14T16:17:12.679Z"}