risingwavelabs/risingwave · error · SinkError

`{}` must be {}, or {}

Error message

`{}` must be {}, or {}

What it means

The Doris sink config requires the `type` property to be either 'append-only' or 'upsert'. Any other value passed through the WITH options map fails deserialization validation and raises this config error.

Source

Thrown at src/connector/src/sink/doris.rs:118

    #[serde(flatten)]
    pub unknown_fields: std::collections::HashMap<String, String>,
}

crate::impl_sink_unknown_fields!(DorisConfig);

impl EnforceSecret for DorisConfig {
    fn enforce_one(prop: &str) -> crate::error::ConnectorResult<()> {
        DorisCommon::enforce_one(prop)
    }
}

impl DorisConfig {
    pub fn from_btreemap(properties: BTreeMap<String, String>) -> Result<Self> {
        let config =
            serde_json::from_value::<DorisConfig>(serde_json::to_value(properties).unwrap())
                .map_err(|e| SinkError::Config(anyhow!(e)))?;
        if config.r#type != SINK_TYPE_APPEND_ONLY && config.r#type != SINK_TYPE_UPSERT {
            return Err(SinkError::Config(anyhow!(
                "`{}` must be {}, or {}",
                SINK_TYPE_OPTION,
                SINK_TYPE_APPEND_ONLY,
                SINK_TYPE_UPSERT
            )));
        }
        Ok(config)
    }
}

#[derive(Debug)]
pub struct DorisSink {
    pub config: DorisConfig,
    schema: Schema,
    pk_indices: Vec<usize>,
    is_append_only: bool,
}

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Set the sink `type` option to exactly `append-only` or `upsert` (lowercase).
  2. Check for typos or capitalization differences in the WITH clause.
  3. If you need other sink modes, use a connector that supports them; Doris sink supports only these two.

Example fix

// before
WITH (
  'connector' = 'doris',
  'type' = 'overwrite'
)
// after
WITH (
  'connector' = 'doris',
  'type' = 'upsert'
)
Defensive patterns

Strategy: validation

Validate before calling

const SINK_TYPE: &str = "upsert";
assert!(matches!(SINK_TYPE, "append-only" | "upsert"));

Type guard

fn valid_doris_type(t: &str) -> bool { t == "append-only" || t == "upsert" }

Try / catch

match DorisConfig::from_btreemap(props) {
    Ok(c) => build_sink(c),
    Err(SinkError::Config(e)) => eprintln!("fix sink `type` option: {e}"),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Creating a Doris sink whose WITH option `type` (SINK_TYPE_OPTION) is set to anything other than `append-only` or `upsert`, e.g. `type='overwrite'` or a misspelled value.

Common situations: Typos in CREATE SINK WITH options; copying a config from another sink connector (Kafka allows other types); case-sensitivity mistakes like `Type='UPSERT'`.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/903359afa27b9a25. Report an issue: GitHub.