risingwavelabs/risingwave · error · SinkError::Iceberg

{e}

Error message

{e}

What it means

This error wraps a failure from the Iceberg catalog's `table_exists` check. Before creating the table, the code queries the catalog to see whether the table already exists; any catalog-level failure (network, auth, namespace missing, REST error) is wrapped into SinkError::Iceberg with the raw catalog error message.

Source

Thrown at src/connector/src/sink/iceberg/create_table.rs:112

}

/// Returns `true` if this call created the table, `false` if it already existed.
pub(super) async fn create_table_if_not_exists_impl(
    config: &IcebergConfig,
    param: &SinkParam,
) -> Result<bool> {
    let catalog = config.create_catalog().await?;
    let table_id = config
        .full_table_name()
        .context("Unable to parse table name")?;
    let namespace = table_id.namespace().clone();
    let table_name = table_id.name().to_owned();
    create_namespace_if_not_exists(catalog.as_ref(), &namespace).await?;

    if catalog
        .table_exists(&table_id)
        .await
        .map_err(|e| SinkError::Iceberg(anyhow!(e)))?
    {
        return Ok(false);
    }

    if config.table_format_version() < FormatVersion::V3
        && let Some(column) = param
            .columns
            .iter()
            .find(|column| column.data_type.contains_variant())
    {
        return Err(SinkError::Config(anyhow!(
            "creating an Iceberg table with VARIANT column `{}` requires `format_version = '3'`",
            column.name
        )));
    }

    let iceberg_create_table_arrow_convert = IcebergCreateTableArrowConvert::default();
    // convert risingwave schema -> arrow schema -> iceberg schema

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Inspect the wrapped `{e}` message — it is the underlying catalog client error — and fix the root cause (URL, auth, DNS).
  2. Verify catalog connectivity from the RisingWave host (curl the REST catalog endpoint / check the metastore).
  3. Confirm catalog.name/uri/authentication options in the sink config are correct for the catalog type.
  4. Retry if the failure was transient (network blip, catalog restart).

Example fix

// before
catalog.name = 'rest', catalog.uri = 'http://iceberg-catalog:8181' // service down
// after: fix endpoint/credentials or start the catalog service, then retry
CREATE SINK ... WITH (connector='iceberg', catalog.type='rest', catalog.uri='http://correct-host:8181', ...);
Defensive patterns

Strategy: retry

Validate before calling

// Check catalog reachability before creating the sink
curl -sS -o /dev/null -w '%{http_code}' http://iceberg-catalog:8181/v1/config

Try / catch

match create_table_if_not_exists(...).await {
    Err(SinkError::Iceberg(e)) if is_transient(&e) => retry_with_backoff(3, || create_table_if_not_exists(...)),
    other => other?,
}

Prevention

When it happens

Trigger: create_table_if_not_exists_impl calls catalog.table_exists(&table_id) and the catalog returns Err — e.g. the REST/Hive/Glue catalog is unreachable, credentials are invalid, or the namespace does not resolve.

Common situations: Misconfigured catalog URI or credentials in the sink WITH options; network egress blocked from the RisingWave node to the catalog service; catalog service down; table identifier malformed for the catalog type.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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