risingwavelabs/risingwave · error · SinkError::Config
(serde_json deserialization error)
Error message
(serde_json deserialization error)
What it means
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.
Source
Thrown at src/connector/src/sink/lancedb.rs:141
#[derive(Clone, Debug, Deserialize, WithOptions)]
pub struct LanceDbConfig {
#[serde(flatten)]
pub common: LanceDbCommon,
pub r#type: String,
/// Whether to use RisingWave's two-phase commit framework for exactly-once commits.
/// Defaults to true. Set to false to use single-phase commits.
#[serde_as(as = "Option<DisplayFromStr>")]
pub is_exactly_once: Option<bool>,
}
impl LanceDbConfig {
pub fn from_btreemap(properties: BTreeMap<String, String>) -> Result<Self> {
let config = serde_json::from_value::<LanceDbConfig>(
serde_json::to_value(properties).map_err(|e| SinkError::LanceDb(e.into()))?,
)
.map_err(|e| SinkError::Config(anyhow!(e)))?;
Ok(config)
}
}
// ---------------------------------------------------------------------------
// Sink
// ---------------------------------------------------------------------------
#[derive(Debug)]
pub struct LanceDbSink {
pub config: LanceDbConfig,
param: SinkParam,
}
impl EnforceSecret for LanceDbSink {
fn enforce_secret<'a>(
_prop_iter: impl Iterator<Item = &'a str>,
) -> crate::error::ConnectorResult<()> {View on GitHub (pinned to 6469eb736d)
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
Example fix
// before CREATE SINK s INTO lancedb WITH ( 'connector' = 'lancedb', 'lancedb.url' = '/tmp/lancedb' ); // after CREATE SINK s INTO lancedb WITH ( 'connector' = 'lancedb', 'lancedb.uri' = '/tmp/lancedb', 'lancedb.table' = 'my_table' );
Defensive patterns
Strategy: validation
Validate before calling
const REQUIRED = ['connector','lancedb.uri','lancedb.table'];
function validateProps(props) {
for (const k of REQUIRED) if (!(k in props)) throw new Error(`missing ${k}`);
const allowed = new Set([...REQUIRED, 'type', 'is_exactly_once', 'commit_checkpoint_interval']);
for (const k of Object.keys(props)) if (!allowed.has(k)) throw new Error(`unknown option ${k}`);
} Try / catch
try { const cfg = LanceDbConfig.from_btreemap(props); } catch (e) { logConfigError(e, props); throw; } Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
Related errors
- SinkError::Config(anyhow!(e))
- {serde_json deserialization error for PulsarConfig from prop
- {serde_json deserialization error for RedisConfig from prope
- SinkError::Config(anyhow!(e))
- You can't use the macro on this type
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/d27ea2bc3bcd9bb2.
Report an issue: GitHub.