risingwavelabs/risingwave · error · SinkError

config deserialization error: {e}

Error message

config deserialization error: {e}

What it means

RisingWave's azblob file sink builds an AzblobConfig by converting the user's WITH options BTreeMap into a JSON value and deserializing it with serde_json::from_value. When any option is missing, has an unexpected type, or is not a recognized field, serde fails and the error is wrapped in SinkError::Config with the message "config deserialization error: {e}". It means the CREATE SINK options could not be parsed into the connector's typed config struct.

Source

Thrown at src/connector/src/sink/file_sink/azblob.rs:113

pub struct AzblobSink;

impl UnknownFields for AzblobConfig {
    fn unknown_fields(&self) -> HashMap<String, String> {
        self.unknown_fields.clone()
    }
}

crate::impl_sink_unknown_fields!(AzblobConfig);

impl OpendalSinkBackend for AzblobSink {
    type Properties = AzblobConfig;

    const SINK_NAME: &'static str = AZBLOB_SINK;

    fn from_btreemap(btree_map: BTreeMap<String, String>) -> Result<Self::Properties> {
        let config =
            serde_json::from_value::<AzblobConfig>(serde_json::to_value(btree_map).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)
    }

    fn new_operator(properties: AzblobConfig) -> Result<Operator> {
        FileSink::<AzblobSink>::new_azblob_sink(properties)
    }

    fn get_path(properties: Self::Properties) -> String {
        properties.common.path
    }

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Check the error's inner serde message: it names the exact missing/unknown/invalid field; fix that WITH option in CREATE SINK.
  2. Verify required azblob options are present: azblob_container_name, azblob_account_name, azblob_access_key, plus r#type, path, and format options.
  3. Correct any misspelled or unsupported option names and remove options not defined on AzblobConfig.
  4. Confirm credentials are plain string values with no characters that break option parsing.
  5. Consult the azblob sink documentation for the current option list, since fields can change between versions.

Example fix

// before
CREATE SINK s FROM mv WITH (
  connector = 'azblob',
  container_name = 'mycontainer',
  type = 'append-only'
);
// after (correct option names + required fields)
CREATE SINK s FROM mv WITH (
  connector = 'azblob',
  azblob_container_name = 'mycontainer',
  azblob_account_name = 'myaccount',
  azblob_access_key = 'secret-key',
  r#type = 'append-only',
  path = 'exports/'
);
Defensive patterns

Strategy: validation

Validate before calling

const REQUIRED: [&str; 4] = ["azblob_container_name", "azblob_account_name", "azblob_access_key", "path"];
for k in REQUIRED {
    if !opts.contains_key(k) {
        return Err(format!("missing azblob sink option: {k}"));
    }
}
match opts.get("r#type").map(String::as_str) {
    Some("append-only") | Some("upsert") => {}
    other => return Err(format!("r#type must be append-only or upsert, got {other:?}")),
}

Try / catch

match AzblobSink::from_btreemap(opts) {
    Ok(cfg) => proceed(cfg),
    Err(SinkError::Config(e)) => eprintln!("fix sink WITH options: {e:#}"),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: CREATE SINK with connector='azblob' where a required field (e.g. azblob_container_name, azblob_account_name, azblob_access_key, path, r#type) is absent, or a field is given a wrongly-typed value, or an unknown/misspelled option name is supplied so serde deserialization of BTreeMap -> AzblobConfig fails.

Common situations: Typo in a WITH option key (e.g. 'container' instead of 'azblob_container_name'); forgetting the access key or account name; copying options from another sink connector (s3/gcs) whose field names differ; newer RisingWave versions adding required fields that older create statements lack.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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