risingwavelabs/risingwave · error · SinkError::Config

(dynamic serde_json deserialization error for Turbopuffer si

Error message

(dynamic serde_json deserialization error for Turbopuffer sink properties)

What it means

TurbopufferConfig::from_btreemap deserializes the sink's properties map into TurbopufferConfig via JSON round-trip; serde reports missing/invalid fields, and the sink wraps it as a Config error. It means required sink WITH options are missing or have wrong types.

Source

Thrown at src/connector/src/sink/turbopuffer.rs:100

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

crate::impl_sink_unknown_fields!(TurbopufferConfig);

impl EnforceSecret for TurbopufferConfig {
    const ENFORCE_SECRET_PROPERTIES: phf::Set<&'static str> = phf::phf_set! {
        "api_key",
    };
}

impl TurbopufferConfig {
    fn from_btreemap(values: BTreeMap<String, String>) -> Result<Self> {
        let config = serde_json::from_value::<TurbopufferConfig>(
            serde_json::to_value(values).expect("serialize sink properties"),
        )
        .map_err(|e| SinkError::Config(anyhow!(e)))?;
        if config.write_batch_size == 0 {
            return Err(SinkError::Config(anyhow!(
                "`write_batch_size` must be greater than 0"
            )));
        }
        if config.max_linger_second == 0 {
            return Err(SinkError::Config(anyhow!(
                "`max_linger_second` must be greater than 0"
            )));
        }
        if config.num_shards == Some(0) {
            return Err(SinkError::Config(anyhow!(
                "`num_shards` must be greater than 0"
            )));
        }
        Ok(config)
    }
}

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Check the error detail for which field failed (missing field 'x' / invalid type) and add/fix that WITH property
  2. Verify against current Turbopuffer sink docs for required property names
  3. Quote string values correctly in the CREATE SINK statement

Example fix

// before
WITH (connector = 'turbopuffer', region = 'aws-us-east-1') // missing api_key
// after
WITH (connector = 'turbopuffer', region = 'aws-us-east-1', api_key = '...', namespace_column = 'ns');
Defensive patterns

Strategy: validation

Validate before calling

const required = ['api_key','region']; const missing = required.filter(k => !(k in props)); if (missing.length) throw new Error('missing: ' + missing)

Type guard

const isTurbopufferConfig = (c) => typeof c?.api_key === 'string' && typeof c?.region === 'string';

Try / catch

catch (SinkError::Config(e)) { read serde detail (missing field / invalid type) and fix the WITH option }

Prevention

When it happens

Trigger: CREATE SINK ... WITH (connector='turbopuffer', ...) where required properties (e.g. api_key, namespace_column, region) are missing or have wrong types.

Common situations: Typo in property name; missing api key; passing numeric options as wrong JSON type; stale property names after connector updates.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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