risingwavelabs/risingwave · error · SinkError
Iceberg error
Error message
Iceberg error: {0} What it means
A `SinkError::Iceberg` variant built from an `anyhow::Error`. RisingWave's Iceberg sink throws this whenever the underlying `icelake`/iceberg writer or catalog operations fail; the display string is "Iceberg error: {0}" and the cause chain plus backtrace are preserved. It is a generic umbrella for all Iceberg-data-path failures in the sink.
Solutions
- Read the wrapped anyhow message and its `source` chain — it points to the failing stage (catalog open, parquet write, commit).
- Verify catalog properties in the sink `WITH` options (catalog type, URI, warehouse, namespace, table) and the object-store credentials/endpoint.
- Compare the sink's derived schema with the target Iceberg table schema; drop/recreate or evolve the table so they match.
- Retry or investigate commit failures — concurrent writers can conflict; ensure only expected writers commit to the table.
Defensive patterns
Strategy: try-catch
Validate before calling
async fn check_iceberg_target(catalog: &dyn Catalog, ns: &str, table: &str) -> anyhow::Result<()> {
let identifiers = catalog.list_tables(&NamespaceIdent::from_str(ns)?).await?;
anyhow::ensure!(identifiers.iter().any(|t| t.name() == table), "iceberg table {ns}.{table} not found");
Ok(())
} Type guard
fn as_iceberg_error(err: &SinkError) -> Option<&anyhow::Error> {
if let SinkError::Iceberg(e) = err { Some(e) } else { None }
} Try / catch
match sink.commit().await {
Err(SinkError::Iceberg(e)) => {
log::error!("iceberg failure: {e:#}"); // full cause chain
// classify: config vs transient commit conflict, then retry or fix config
}
Err(e) => return Err(e.into()),
Ok(_) => {}
} Prevention
- Dry-run catalog and object-store connectivity (list namespace/table) before creating the sink.
- Keep sink schema and target Iceberg table schema in sync; evolve the table intentionally.
- Use distinct writer identities to avoid frequent commit conflicts.
- Log with `{e:#}` (anyhow alternate) to see the full source chain of the wrapped error.
When it happens
Trigger: Writing records to an Iceberg table from the sink: opening the table via the catalog, building/writing parquet data files, committing snapshots (commits to the catalog), or any `icelake` API returning an error that the sink converts with `.into()`/`anyhow!`.
Common situations: Wrong catalog configuration (REST/Hive/Glue catalog URL, warehouse path, credentials); S3/object-store misconfiguration (endpoint, region, bucket permissions); schema mismatch between the RisingWave sink plan and the existing Iceberg table schema; concurrent commit conflicts or stale metadata after table evolution.
Related errors
- `enable_pk_index` is only supported for upsert iceberg sink
- ALTER SINK_RATE_LIMIT is not for sink into table
- Avro error
- Can't create iceberg sink write result from empty data!
- ClickHouse error
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/091d010e964bb357.
Report an issue: GitHub.
Appendix: source
Thrown at src/connector/src/sink/mod.rs:1108
#[error("Kafka error: {0}")]
Kafka(#[from] rdkafka::error::KafkaError),
#[error("Kinesis error: {0}")]
Kinesis(
#[source]
#[backtrace]
anyhow::Error,
),
#[error("Remote sink error: {0}")]
Remote(
#[source]
#[backtrace]
anyhow::Error,
),
#[error("Encode error: {0}")]
Encode(String),
#[error("Avro error: {0}")]
Avro(#[from] apache_avro::Error),
#[error("Iceberg error: {0}")]
Iceberg(
#[source]
#[backtrace]
anyhow::Error,
),
#[error("config error: {0}")]
Config(
#[source]
#[backtrace]
anyhow::Error,
),
#[error("coordinator error: {0}")]
Coordinator(
#[source]
#[backtrace]
anyhow::Error,
),
#[error("ClickHouse error: {0}")]View on GitHub (pinned to 6469eb736d)