risingwavelabs/risingwave · error · SinkError::Config

{e}

Error message

{e}

What it means

`StarrocksConfig::from_btreemap` converts the sink's `WITH` options into a `StarrocksConfig` by round-tripping through serde_json and deserializing into the struct. If serde rejects the properties (unknown/missing/incorrectly-typed fields), the serde error is wrapped verbatim in a `SinkError::Config` with this message (`{e}` is the serde error text). It means the sink's user-provided options did not match the expected config shape.

Source

Thrown at src/connector/src/sink/starrocks.rs:159

}

crate::impl_sink_unknown_fields!(StarrocksConfig);

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

fn default_commit_checkpoint_interval() -> u64 {
    DEFAULT_COMMIT_CHECKPOINT_INTERVAL_WITH_SINK_DECOUPLE
}

impl StarrocksConfig {
    pub fn from_btreemap(properties: BTreeMap<String, String>) -> Result<Self> {
        let config =
            serde_json::from_value::<StarrocksConfig>(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
            )));
        }
        if config.commit_checkpoint_interval == 0 {
            return Err(SinkError::Config(anyhow!(
                "`commit_checkpoint_interval` must be greater than 0"
            )));
        }
        if let Some(0) = config.max_batch_size_bytes {
            return Err(SinkError::Config(anyhow!(
                "`starrocks.max_batch_size_bytes` must be greater than 0"
            )));
        }

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Read the embedded serde error text (`{e}` in the message) — it names the exact field and mismatch.
  2. Compare your WITH options against StarrocksConfig's expected fields and fix names/types.
  3. Ensure required StarRocks options (url, database/table, username, password, type) are all present.
  4. Quote complex values correctly in the CREATE SINK statement (single quotes for strings).

Example fix

-- before (missing/misspelled option)
CREATE SINK s FROM mv WITH (connector='starrocks', starrocks.host='...', type='append_only');
-- after
CREATE SINK s FROM mv WITH (connector='starrocks', starrocks.url='jdbc:mysql://fe:9030', starrocks.table='t', type='append_only');
Defensive patterns

Strategy: validation

Validate before calling

// Rust: verify required StarRocks options before building the sink
fn validate_starrocks_props(props: &BTreeMap<String, String>) -> Result<(), String> {
    for k in ["starrocks.url", "starrocks.table", "type"] {
        if !props.contains_key(k) { return Err(format!("missing {k}")); }
    }
    Ok(())
}

Try / catch

match StarrocksConfig::from_btreemap(props) {
    Err(SinkError::Config(e)) => { log::error!("bad starrocks config: {e}"); fix_props_and_retry(); }
    other => other,
}

Prevention

When it happens

Trigger: Creating a StarRocks sink whose WITH options fail `serde_json::from_value::<StarrocksConfig>` — e.g. missing required `starrocks.url`/`table` fields, a field with the wrong type (string vs number), or unknown keys when deny_unknown_fields applies.

Common situations: Typos in option names (`starrocks.host` vs `url`); quoting issues so a numeric option arrives as a string; forgetting required options; passing options reserved for another connector.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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