risingwavelabs/risingwave · error · iceberg::Error (ErrorKind::Unexpected)

Failed to update iceberg table.

Error message

Failed to update iceberg table.

What it means

JniCatalog::update_table wraps any error from the JNI commit/update call (Java exception during table commit, JNIEnv error, or JoinError from a panicked task) into this Unexpected iceberg error with source attached. The table commit was not applied.

Source

Thrown at src/connector/src/connector_common/iceberg/jni_catalog.rs:533

                );

                let table_metadata = response.metadata;

                let file_io = FileIOBuilder::new(Arc::new(OpenDalResolvingStorageFactory::new()))
                    .with_props(file_io_props.iter())
                    .build();

                Ok(Table::builder()
                    .file_io(file_io)
                    .identifier(commit.identifier().clone())
                    .metadata(table_metadata)
                    .runtime(runtime)
                    .build()?)
            })
        })
        .await
        .map_err(|e| {
            iceberg::Error::new(
                iceberg::ErrorKind::Unexpected,
                "Failed to update iceberg table.",
            )
            .with_source(e)
        })
    }
}

impl Drop for JniCatalogInner {
    fn drop(&mut self) {
        let _ = execute_with_jni_env(self.jvm, |env| {
            call_method!(env, self.java_catalog.as_obj(), {void close()})
                .with_context(|| "Failed to close iceberg catalog".to_owned())?;
            Ok(())
        })
        .inspect_err(
            |e| tracing::error!(error = ?e.as_report(), "Failed to close iceberg catalog"),
        );

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Inspect the source error chain for commit rejections or Java exceptions
  2. Re-load the table to get fresh metadata and retry the commit (conflict handling)
  3. Verify credentials and backend catalog availability
  4. Ensure JVM/classpath is correctly configured for commit-heavy operations
Defensive patterns

Strategy: retry

Validate before calling

// Reload fresh table metadata before committing to avoid stale-commit conflicts
let fresh = catalog.load_table(commit.table()).await?;
// verify requirements against fresh metadata before update_table

Type guard

fn is_jni_update_failure(err: &iceberg::Error) -> bool {
    err.kind() == iceberg::ErrorKind::Unexpected && err.message().contains("Failed to update iceberg table.")
}

Try / catch

match catalog.update_table(commit).await {
    Err(e) if e.message().contains("Failed to update iceberg table.") => {
        // reload table, rebuild commit, retry with backoff
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling update_table with a TableCommit (schema evolution, partition spec updates, commit of new snapshots) where the underlying Java catalog commit fails or the block_in_place task panics.

Common situations: Commit conflicts (the Java side rejects a stale metadata version), auth/backend failures during snapshot commit, JVM misconfiguration when RisingWave commits changes to an Iceberg table.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


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