{"record":{"id":"efbe62548f30e192","repo":"risingwavelabs/risingwave","slug":"sinkerror-config-anyhow-e-efbe62","errorCode":null,"errorMessage":"SinkError::Config(anyhow!(e))","messagePattern":"SinkError::Config\\(anyhow!\\(e\\)\\)","errorType":"validation","errorClass":"SinkError::Config","httpStatus":null,"severity":"error","filePath":"src/connector/src/sink/snowflake_redshift/redshift.rs","lineNumber":152,"sourceCode":"    3600 // Default to 1 hour\n}\n\nfn default_intermediate_interval_schedule() -> u64 {\n    1800 // Default to 0.5 hour\n}\n\nfn default_batch_insert_rows() -> u32 {\n    4096 // Default batch size\n}\n\nfn default_with_s3() -> bool {\n    true\n}\n\nimpl RedShiftConfig {\n    pub fn from_btreemap(properties: BTreeMap<String, String>) -> Result<Self> {\n        serde_json::from_value::<RedShiftConfig>(serde_json::to_value(properties).unwrap())\n            .map_err(|e| SinkError::Config(anyhow!(e)))\n    }\n\n    pub fn build_client(&self) -> Result<JdbcJniClient> {\n        let mut jdbc_url = self.jdbc_url.clone();\n        if let Some(username) = &self.username {\n            jdbc_url = format!(\"{}?user={}\", jdbc_url, username);\n        }\n        if let Some(password) = &self.password {\n            jdbc_url = format!(\"{}&password={}\", jdbc_url, password);\n        }\n        JdbcJniClient::new(jdbc_url)\n    }\n}\n\n#[derive(Debug)]\npub struct RedshiftSink {\n    config: RedShiftConfig,\n    param: SinkParam,","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/sink/snowflake_redshift/redshift.rs#L134-L170","documentation":"`RedShiftConfig::from_btreemap` deserializes the sink's user-supplied property map into a `RedShiftConfig` via serde_json; any missing required field or invalid value produces a serde error that is wrapped as SinkError::Config. It means the Redshift sink properties are malformed.","triggerScenarios":"Creating a Redshift sink whose properties BTreeMap is missing required keys (e.g. jdbc-url, table, arn) or has wrong-typed values, so `serde_json::from_value` fails.","commonSituations":"Typos in CREATE SINK property names; missing mandatory fields in the connector WITH clause; values that don't deserialize into the configured Rust types.","solutions":["Check the error text from serde naming the missing/invalid field and fix the CREATE SINK properties","Ensure all required Redshift options are provided (jdbc_url, table, schema, region, s3 settings as applicable)","Validate property names against the Redshift sink documentation before creating the sink"],"exampleFix":"// before\nWITH ( connector = 'redshift', tabel = 'my_table' )\n-- after\nWITH ( connector = 'redshift', table = 'my_table', jdbc_url = '...', ... )","handlingStrategy":"validation","validationCode":"// validate required redshift properties before creating the sink\nfn validate_redshift_props(props: &BTreeMap<String, String>) -> Result<(), String> {\n    for k in [\"jdbc_url\", \"table\", \"schema\"] {\n        if !props.contains_key(k) { return Err(format!(\"missing required property: {}\", k)); }\n    }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"match RedShiftConfig::from_btreemap(props) {\n    Ok(cfg) => cfg,\n    Err(e) if matches!(&e, SinkError::Config(_)) => { log::error!(\"invalid redshift sink config: {}\", e); return Err(e); }\n    Err(e) => return Err(e),\n}","preventionTips":["Copy property names from official docs, avoid typos","Validate sink WITH options before CREATE SINK","Keep a checklist of required Redshift fields"],"tags":["rust","risingwave","sink","redshift","config","serde"],"backgroundTag":"missing-required-config-field","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}