{"record":{"id":"aaf4a973f73456f3","repo":"risingwavelabs/risingwave","slug":"dynamic-serde-json-deserialization-error-for-adbc","errorCode":null,"errorMessage":"(dynamic serde_json deserialization error for AdbcSnowflakeSplit restore)","messagePattern":"\\(dynamic serde_json deserialization error for AdbcSnowflakeSplit restore\\)","errorType":"validation","errorClass":"ConnectorError","httpStatus":null,"severity":"error","filePath":"src/connector/src/source/adbc_snowflake/mod.rs","lineNumber":335,"sourceCode":"}\n\n/// Split for ADBC Snowflake source.\n/// Since Snowflake queries are executed as a whole, we use a single split with the query as the identifier.\n#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Hash)]\npub struct AdbcSnowflakeSplit {\n    /// The split identifier (typically based on the query).\n    pub split_id: String,\n    /// The SQL query to execute.\n    pub query: String,\n}\n\nimpl SplitMetaData for AdbcSnowflakeSplit {\n    fn id(&self) -> SplitId {\n        self.split_id.clone().into()\n    }\n\n    fn restore_from_json(value: JsonbVal) -> ConnectorResult<Self> {\n        serde_json::from_value(value.take()).map_err(|e| anyhow!(e).into())\n    }\n\n    fn encode_to_json(&self) -> JsonbVal {\n        serde_json::to_value(self.clone()).unwrap().into()\n    }\n\n    fn update_offset(&mut self, _last_seen_offset: String) -> ConnectorResult<()> {\n        // ADBC Snowflake doesn't have offset-based reading for now\n        Ok(())\n    }\n}\n\n/// Split enumerator for ADBC Snowflake source.\npub struct AdbcSnowflakeSplitEnumerator {\n    properties: AdbcSnowflakeProperties,\n}\n\n#[async_trait]","sourceCodeStart":317,"sourceCodeEnd":353,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/source/adbc_snowflake/mod.rs#L317-L353","documentation":"AdbcSnowflakeSplit::restore_from_json deserializes a previously encoded split's JsonbVal back into the AdbcSnowflakeSplit struct during state recovery (e.g. after a failover or source restart). If the stored JSON does not match the struct's serde expectations (missing/renamed fields, wrong types, corrupted state), serde_json fails and the underlying error is wrapped into a ConnectorResult. The message shown is the generic context; the real cause is in the chained serde error.","triggerScenarios":"Recovering a Snowflake (ADBC) source split from meta state where the persisted JSON was written by a different RisingWave version with a changed split struct layout, or where the stored value is malformed/corrupted.","commonSituations":"Upgrading RisingWave across versions where AdbcSnowflakeSplit fields were renamed or restructured and old checkpoint state is restored; manually edited or corrupted meta state.","solutions":["Check the full chained serde error to see which field mismatched.","Restart the source after clearing stale checkpoint/split state so splits are re-encoded with the current schema.","Ensure the RisingWave cluster (meta and compute) is on a single consistent version — no mixed-version restore across an upgrade.","If this is reproducible after an upgrade, report it; the split serde format may need a compatibility shim."],"exampleFix":"// no user code fix; operational remedy:\n// stop source → clear stale split state → recreate source so AdbcSnowflakeSplit is re-encoded by the current version","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// recover split state defensively\nmatch AdbcSnowflakeSplit::restore_from_json(json) {\n    Ok(split) => split,\n    Err(e) => {\n        tracing::warn!(error = %e, \"stale split state; re-encoding from scratch\");\n        AdbcSnowflakeSplit::default() // or trigger split re-planning\n    }\n}","preventionTips":["Keep the whole cluster on one RisingWave version during and after upgrades.","Follow the documented rolling-upgrade procedure so old split state is not restored by newer code.","Clear stale source checkpoint state when moving between incompatible versions."],"tags":["snowflake","source","serde","deserialization","state-recovery"],"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-14T11:17:12.474Z"}