{"record":{"id":"d27ea2bc3bcd9bb2","repo":"risingwavelabs/risingwave","slug":"serde-json-deserialization-error","errorCode":null,"errorMessage":"(serde_json deserialization error)","messagePattern":"\\(serde_json deserialization error\\)","errorType":"validation","errorClass":"SinkError::Config","httpStatus":null,"severity":"error","filePath":"src/connector/src/sink/lancedb.rs","lineNumber":141,"sourceCode":"#[derive(Clone, Debug, Deserialize, WithOptions)]\npub struct LanceDbConfig {\n    #[serde(flatten)]\n    pub common: LanceDbCommon,\n\n    pub r#type: String,\n\n    /// Whether to use RisingWave's two-phase commit framework for exactly-once commits.\n    /// Defaults to true. Set to false to use single-phase commits.\n    #[serde_as(as = \"Option<DisplayFromStr>\")]\n    pub is_exactly_once: Option<bool>,\n}\n\nimpl LanceDbConfig {\n    pub fn from_btreemap(properties: BTreeMap<String, String>) -> Result<Self> {\n        let config = serde_json::from_value::<LanceDbConfig>(\n            serde_json::to_value(properties).map_err(|e| SinkError::LanceDb(e.into()))?,\n        )\n        .map_err(|e| SinkError::Config(anyhow!(e)))?;\n        Ok(config)\n    }\n}\n\n// ---------------------------------------------------------------------------\n// Sink\n// ---------------------------------------------------------------------------\n\n#[derive(Debug)]\npub struct LanceDbSink {\n    pub config: LanceDbConfig,\n    param: SinkParam,\n}\n\nimpl EnforceSecret for LanceDbSink {\n    fn enforce_secret<'a>(\n        _prop_iter: impl Iterator<Item = &'a str>,\n    ) -> crate::error::ConnectorResult<()> {","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/sink/lancedb.rs#L123-L159","documentation":"LanceDbConfig::from_btreemap serializes the user's WITH-option map to JSON and deserializes it into LanceDbConfig. A mismatch between provided option keys/types and the struct definition produces a serde error wrapped as SinkError::Config, so the sink cannot be built.","triggerScenarios":"CREATE SINK ... WITH (...) where an option is misspelled, an unexpected/unknown key is given, or a field's value cannot deserialize into the declared type (e.g., a non-numeric string for a numeric field).","commonSituations":"Typos in lancedb.uri / lancedb.table keys, leftover options from another connector, quoting issues in SQL string literals, or copy-pasted options with wrong types.","solutions":["Read the serde error message; it names the offending field and expected type","Fix the misspelled or mistyped option in the WITH clause","Only use documented options: lancedb.uri, lancedb.table and common sink options","Remove options not defined on LanceDbConfig"],"exampleFix":"// before\nCREATE SINK s INTO lancedb WITH (\n  'connector' = 'lancedb',\n  'lancedb.url' = '/tmp/lancedb'\n);\n// after\nCREATE SINK s INTO lancedb WITH (\n  'connector' = 'lancedb',\n  'lancedb.uri' = '/tmp/lancedb',\n  'lancedb.table' = 'my_table'\n);","handlingStrategy":"validation","validationCode":"const REQUIRED = ['connector','lancedb.uri','lancedb.table'];\nfunction validateProps(props) {\n  for (const k of REQUIRED) if (!(k in props)) throw new Error(`missing ${k}`);\n  const allowed = new Set([...REQUIRED, 'type', 'is_exactly_once', 'commit_checkpoint_interval']);\n  for (const k of Object.keys(props)) if (!allowed.has(k)) throw new Error(`unknown option ${k}`);\n}","typeGuard":null,"tryCatchPattern":"try { const cfg = LanceDbConfig.from_btreemap(props); } catch (e) { logConfigError(e, props); throw; }","preventionTips":["Copy option names from official docs, not memory","Use lowercase snake_case keys exactly as documented","Validate the WITH clause against the documented option list before running"],"tags":["rust","serde","config"],"backgroundTag":"json-unmarshal-failed","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"}