risingwavelabs/risingwave · error · iceberg::Error (ErrorKind::Unexpected)
Failed to load iceberg table.
Error message
Failed to load iceberg table.
What it means
JniCatalog::load_table wraps any error surfaced from the JNI call stack (Java exception, JNIEnv failure, or join error) into this generic Unexpected iceberg error, attaching the original as its source. It is a wrapper error; the real cause is in with_source(e).
Source
Thrown at src/connector/src/connector_common/iceberg/jni_catalog.rs:393
);
let table_metadata = resp.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(table)
.metadata(table_metadata)
.runtime(runtime)
.build())
})
})
.await
.map_err(|e| {
iceberg::Error::new(
iceberg::ErrorKind::Unexpected,
"Failed to load iceberg table.",
)
.with_source(e)
})?
}
/// Drop a table from the catalog.
async fn drop_table(&self, table: &TableIdent) -> iceberg::Result<()> {
let inner = self.inner.clone();
let table = table.to_owned();
execute_blocking_jni(move || {
execute_with_jni_env(inner.jvm, |env| {
let table_name_str = table.to_string();
let table_name_jstr = env.new_string(&table_name_str).unwrap();
call_method!(env, inner.java_catalog.as_obj(), {boolean dropTable(String)},View on GitHub (pinned to 6469eb736d)
Solutions
- Inspect the with_source error chain to find the underlying JNI/Java exception
- Verify catalog properties (uri, warehouse, catalog type) are correct and complete
- Ensure the JVM is initialized and the Iceberg Java runtime jar is on the classpath
- Check the Java-side catalog connectivity (network, credentials) to the backend
- Look for panics in the surrounding closure in jni_catalog.rs logs
Defensive patterns
Strategy: try-catch
Validate before calling
// Validate catalog config before calling load
assert!(!props.get("uri").unwrap_or_default().is_empty(), "catalog uri required");
// Ensure JVM is up before JNI catalog use
// jvm::ensure_initialized()?; Type guard
fn is_jni_load_failure(err: &iceberg::Error) -> bool {
err.kind() == iceberg::ErrorKind::Unexpected && err.message().contains("Failed to load iceberg table.")
} Try / catch
match catalog.load_table(&ident).await {
Err(e) if e.message().contains("Failed to load iceberg table.") => {
tracing::error!(source = ?e.source(), "jni load_table failed");
// inspect Java-side cause, retry transient errors
}
other => other,
} Prevention
- Double-check catalog properties (uri, warehouse, type) before calls
- Initialize the JVM and classpath early and fail fast at startup
- Log the full error chain (with_source) for JNI diagnostics
When it happens
Trigger: The Java/JNI catalog call invoked inside tokio::task::block_in_place (from purge_table) returns Err — e.g. Java exception during catalog.loadTable, missing JVM class, bad catalog properties, or a tokio JoinError when the spawned closure panics.
Common situations: Missing or wrong catalog properties (warehouse URI, catalog type) passed to the Java catalog; JVM not initialized or classpath missing the Iceberg runtime; network/auth failure reaching Hive/Gluc/Nessie from the Java side; closure panic in the async block.
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
- Failed to list iceberg namespaces.
- Failed to drop iceberg table.
- register_table is not supported by JniCatalog
- Failed to check iceberg table exists.
- Failed to update iceberg table.
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/13e5a62c2a62d3fe.
Report an issue: GitHub.