risingwavelabs/risingwave · error · SinkError::Config

only append-only LanceDB sink is supported

Error message

only append-only LanceDB sink is supported

What it means

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.

Source

Thrown at src/connector/src/sink/lancedb.rs:216

            inner,
            commit_checkpoint_interval,
        )
        .await?;

        Ok(writer)
    }

    fn validate_alter_config(config: &BTreeMap<String, String>) -> Result<()> {
        LanceDbConfig::from_btreemap(config.clone())?;
        Ok(())
    }

    async fn validate(&self) -> Result<()> {
        // Only append-only is supported
        if self.config.r#type != SINK_TYPE_APPEND_ONLY
            && self.config.r#type != SINK_USER_FORCE_APPEND_ONLY_OPTION
        {
            return Err(SinkError::Config(anyhow!(
                "only append-only LanceDB sink is supported",
            )));
        }

        if self.config.common.commit_checkpoint_interval == 0 {
            return Err(SinkError::Config(anyhow!(
                "`commit_checkpoint_interval` must be greater than 0"
            )));
        }

        // Validate connection
        let conn = self.config.common.create_connection().await?;

        // Validate table exists and schema is compatible
        let table = self.config.common.open_table(&conn).await?;

        // Get the Lance table schema (Arrow schema)
        let lance_schema = table

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Specify type = 'append-only' or 'force_append_only' in the sink definition
  2. If you need upsert semantics, accept duplicates/append-only or choose a different connector that supports upsert
  3. Ensure the upstream MV produces append-only data, or use force_append_only to drop deletes

Example fix

// before
CREATE SINK s FROM mv WITH ('connector'='lancedb', 'type'='upsert', ...);
// after
CREATE SINK s FROM mv WITH ('connector'='lancedb', 'type'='force_append_only', ...);
Defensive patterns

Strategy: validation

Validate before calling

function validateSinkType(type) {
  const ok = ['append-only', 'force_append_only'];
  if (!ok.includes(type)) throw new Error(`lancedb sink requires ${ok.join(' or ')}`);
}

Try / catch

catch (SinkError::Config(e)) if e.includes("only append-only LanceDB sink") { switch the sink type to append-only or use a different connector }

Prevention

When it happens

Trigger: CREATE SINK with type 'upsert' or 'debezium' (or a non-append-only default for the target) against connector='lancedb'.

Common situations: Sinking a materialized view that receives UPDATE/DELETE (non-append-only) changelog stream into LanceDB; users expecting upsert semantics.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/b0982e8806081d0e. Report an issue: GitHub.