risingwavelabs/risingwave · error · SinkError::LanceDb

(underlying lancedb::Error)

Error message

(underlying lancedb::Error)

What it means

A blanket `From<lancedb::Error> for SinkError` conversion: every error returned by the LanceDB Rust SDK (connection failures, table-not-found, IO errors, etc.) is wrapped with anyhow and re-raised as SinkError::LanceDb. The message you see is whatever lancedb::Error carried, so the real cause must be read from the wrapped source chain.

Source

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

            (
                RW_SINK_ID_TRANSACTION_PROPERTY.to_owned(),
                self.sink_id.clone(),
            ),
            (
                RW_EPOCH_TRANSACTION_PROPERTY.to_owned(),
                self.epoch.to_string(),
            ),
        ])
    }
}

// ---------------------------------------------------------------------------
// Error conversion
// ---------------------------------------------------------------------------

impl From<lancedb::Error> for SinkError {
    fn from(value: lancedb::Error) -> Self {
        SinkError::LanceDb(anyhow!(value))
    }
}

// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------

#[cfg(all(test, not(madsim)))]
mod tests {
    use risingwave_common::array::{Array, I32Array, Op, StreamChunk, Utf8Array};
    use risingwave_common::catalog::{ColumnDesc, ColumnId, Field, Schema};
    use risingwave_common::id::SinkId;
    use risingwave_common::types::DataType;

    use super::*;
    use crate::sink::catalog::SinkType;
    use crate::sink::writer::SinkWriter;
    use crate::sink::{SinglePhaseCommitCoordinator, TwoPhaseCommitCoordinator};

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Inspect the anyhow source chain (log with {:#} or {:?}) to find the underlying lancedb::Error cause
  2. Verify sink options: URI, table name, and credentials are correct and reachable from the RisingWave node
  3. Check network connectivity to the LanceDB endpoint (and S3/GCS if object-store backed) and retry transient failures
  4. Confirm the target table exists and was not dropped or locked by another process

Example fix

// before
// error surfaced only as: LanceDB sink error: <short message>
// after
tracing::error!("lancedb sink error: {e:#}"); // full source chain shows root cause
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight: verify the LanceDB endpoint and table are reachable
async fn table_openable(uri: &str, table: &str) -> bool {
    lancedb::connect(uri)
        .unwrap()
        .open_table(table)
        .await
        .is_ok()
}

Type guard

fn underlying_lancedb_error(err: &SinkError) -> Option<&anyhow::Error> {
    match err { SinkError::LanceDb(e) => Some(e), _ => None }
}

Try / catch

match write_result {
    Err(SinkError::LanceDb(e)) => {
        tracing::error!("lancedb op failed: {e:#}"); // full anyhow source chain
        // branch on cause: retry transient network errors, fail on config errors
    }
    other => other,
}

Prevention

When it happens

Trigger: Any `?` on a lancedb SDK call across the sink (open table, append rows, commit), e.g. table creation failing due to a bad URI, network errors to the LanceDB service, or storage-credential problems.

Common situations: Wrong LanceDB URI in sink options, missing credentials for object-store-backed LanceDB, network/firewall issues between RisingWave and the LanceDB service, table deleted externally.

Related errors


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