{"record":{"id":"b0982e8806081d0e","repo":"risingwavelabs/risingwave","slug":"only-append-only-lancedb-sink-is-supported","errorCode":null,"errorMessage":"only append-only LanceDB sink is supported","messagePattern":"only append-only LanceDB sink is supported","errorType":"validation","errorClass":"SinkError::Config","httpStatus":null,"severity":"error","filePath":"src/connector/src/sink/lancedb.rs","lineNumber":216,"sourceCode":"            inner,\n            commit_checkpoint_interval,\n        )\n        .await?;\n\n        Ok(writer)\n    }\n\n    fn validate_alter_config(config: &BTreeMap<String, String>) -> Result<()> {\n        LanceDbConfig::from_btreemap(config.clone())?;\n        Ok(())\n    }\n\n    async fn validate(&self) -> Result<()> {\n        // Only append-only is supported\n        if self.config.r#type != SINK_TYPE_APPEND_ONLY\n            && self.config.r#type != SINK_USER_FORCE_APPEND_ONLY_OPTION\n        {\n            return Err(SinkError::Config(anyhow!(\n                \"only append-only LanceDB sink is supported\",\n            )));\n        }\n\n        if self.config.common.commit_checkpoint_interval == 0 {\n            return Err(SinkError::Config(anyhow!(\n                \"`commit_checkpoint_interval` must be greater than 0\"\n            )));\n        }\n\n        // Validate connection\n        let conn = self.config.common.create_connection().await?;\n\n        // Validate table exists and schema is compatible\n        let table = self.config.common.open_table(&conn).await?;\n\n        // Get the Lance table schema (Arrow schema)\n        let lance_schema = table","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/sink/lancedb.rs#L198-L234","documentation":"The LanceDB sink only supports append-only streams. If the sink type is neither 'append-only' nor the user-forced append-only option, validation rejects the sink because LanceDB rows cannot be updated/deleted by this connector.","triggerScenarios":"CREATE SINK with type 'upsert' or 'debezium' (or a non-append-only default for the target) against connector='lancedb'.","commonSituations":"Sinking a materialized view that receives UPDATE/DELETE (non-append-only) changelog stream into LanceDB; users expecting upsert semantics.","solutions":["Specify type = 'append-only' or 'force_append_only' in the sink definition","If you need upsert semantics, accept duplicates/append-only or choose a different connector that supports upsert","Ensure the upstream MV produces append-only data, or use force_append_only to drop deletes"],"exampleFix":"// before\nCREATE SINK s FROM mv WITH ('connector'='lancedb', 'type'='upsert', ...);\n// after\nCREATE SINK s FROM mv WITH ('connector'='lancedb', 'type'='force_append_only', ...);","handlingStrategy":"validation","validationCode":"function validateSinkType(type) {\n  const ok = ['append-only', 'force_append_only'];\n  if (!ok.includes(type)) throw new Error(`lancedb sink requires ${ok.join(' or ')}`);\n}","typeGuard":null,"tryCatchPattern":"catch (SinkError::Config(e)) if e.includes(\"only append-only LanceDB sink\") { switch the sink type to append-only or use a different connector }","preventionTips":["Check connector capability tables before choosing sink type","Use force_append_only when the upstream may emit updates/deletes you want dropped","Prefer connectors with upsert support when upsert semantics are required"],"tags":["rust","lancedb","sink-validation"],"backgroundTag":"unsupported-operation","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"}