risingwavelabs/risingwave · error · SinkError::Config
{e}
Error message
{e} What it means
SqlServerConfig::from_btreemap deserializes the user-supplied property map into the SqlServerConfig struct via serde_json. If any property fails to deserialize (wrong type, unknown/misspelled field, malformed value), the serde error is wrapped as SinkError::Config.
Source
Thrown at src/connector/src/sink/sqlserver.rs:86
#[serde_as(as = "DisplayFromStr")]
pub max_batch_rows: usize,
pub r#type: String, // accept "append-only" or "upsert"
#[serde(flatten)]
pub unknown_fields: std::collections::HashMap<String, String>,
}
crate::impl_sink_unknown_fields!(SqlServerConfig);
pub fn sql_server_default_schema() -> String {
"dbo".to_owned()
}
impl SqlServerConfig {
pub fn from_btreemap(properties: BTreeMap<String, String>) -> Result<Self> {
let config =
serde_json::from_value::<SqlServerConfig>(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)
}
pub fn full_object_path(&self) -> String {
format!("[{}].[{}].[{}]", self.database, self.schema, self.table)
}
}
impl EnforceSecret for SqlServerConfig {
const ENFORCE_SECRET_PROPERTIES: Set<&'static str> = phf_set! {View on GitHub (pinned to 6469eb736d)
Solutions
- Read the serde error message in `e` — it names the offending field and expected type
- Fix the option name/value in the CREATE SINK ... WITH (...) clause to match SqlServerConfig fields
- Compare against the documented SQL Server sink options list and remove unrelated options
Example fix
// before WITH ( 'max_batch_rows' = 'many' ) // after WITH ( 'max_batch_rows' = '1000' )
Defensive patterns
Strategy: validation
Validate before calling
fn validate_sqlserver_props(props: &BTreeMap<String, String>) -> Result<(), String> {
for k in props.keys() {
if !KNOWN_SQLSERVER_OPTIONS.contains(&k.as_str()) { return Err(format!("unknown option: {}", k)); }
}
if let Some(v) = props.get("max_batch_rows") {
v.parse::<usize>().map_err(|_| format!("max_batch_rows must be numeric, got {}", v))?;
}
Ok(())
} Try / catch
match SqlServerConfig::from_btreemap(props) {
Err(SinkError::Config(e)) => { log_config_error(&e); Err(e) }
other => other,
} Prevention
- Copy sink options only from the SQL Server sink docs
- Validate numeric options parse before submitting
- Keep a canonical example WITH clause and diff against it
When it happens
Trigger: Calling SqlServerConfig::from_btreemap with properties whose keys/values do not match the serde expectations of SqlServerConfig, e.g. non-numeric max_batch_rows, unknown option names (without deny_unknown_fields leniency), or wrong types.
Common situations: Typos in sink WITH options, passing a string where a number is expected, copying options from another sink connector (e.g. Kafka-style options) into the SQL Server sink.
Related errors
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/0fc30685887fc74f.
Report an issue: GitHub.