risingwavelabs/risingwave · error · iceberg::Error (ErrorKind::Unexpected)
Failed to create iceberg table.
Error message
Failed to create iceberg table.
What it means
`JniCatalog::create_table` wraps any failure of the JNI create-table call (Java exception, invalid schema/JSON, catalog rejection, or response parse failure) into an iceberg `Unexpected` error with the message 'Failed to create iceberg table.' and the original error as its source.
Source
Thrown at src/connector/src/connector_common/iceberg/jni_catalog.rs:337
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(TableIdent::new(namespace, creation.name))
.metadata(table_metadata)
.runtime(runtime)
.build())
})
})
.await
.map_err(|e| {
iceberg::Error::new(
iceberg::ErrorKind::Unexpected,
"Failed to create iceberg table.",
)
.with_source(e)
})?
}
/// Load table from the catalog.
async fn load_table(&self, table: &TableIdent) -> iceberg::Result<Table> {
let inner = self.inner.clone();
let file_io_props = self.file_io_props.clone();
let runtime = Runtime::try_current()?;
let table = table.clone();
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();View on GitHub (pinned to 6469eb736d)
Solutions
- Inspect the wrapped source error to find the Java-side exception.
- Verify the table does not already exist in the catalog.
- Check that the namespace exists and credentials/IAM allow table creation at the warehouse location.
- Confirm the table schema (types, identifiers) is supported by the backend catalog.
- Ensure the JNI/JVM environment and classpath are correctly configured.
Defensive patterns
Strategy: try-catch
Validate before calling
// Validate schema and preconditions before JNI create_table
fn can_create(catalog_exists: bool, table_exists: bool, schema_json: &str) -> Result<(), String> {
if !catalog_exists { return Err("namespace does not exist".into()); }
if table_exists { return Err("table already exists".into()); }
if serde_json::from_str::<serde_json::Value>(schema_json).is_err() { return Err("schema is not valid JSON".into()); }
Ok(())
} Try / catch
match catalog.create_table(&ns, ident, schema).await {
Err(e) => {
tracing::error!(source = ?e.source(), "iceberg create_table failed");
// inspect e.source() for Java exception: already-exists vs permissions vs schema
Err(e)
}
Ok(t) => Ok(t),
} Prevention
- Pre-check namespace and table existence before create.
- Confirm IAM permissions on the warehouse location.
- Validate the table schema against backend-supported types before sending over JNI.
- Keep the JVM/JNI environment and classpath correctly configured.
When it happens
Trigger: Calling create_table on a JNI catalog when the JVM-side create fails: invalid schema JSON sent to Java, namespace does not exist, table already exists, permission denied, or the returned result JSON cannot be parsed.
Common situations: CREATE TABLE / CREATE SINK into Iceberg with a schema the Java catalog rejects; table already existing in Glue/Hadoop; missing IAM permissions on the target location; malformed or unsupported column types crossing the JNI boundary.
Related errors
- Failed to list iceberg namespaces.
- Failed to create namespace.
- Failed to check namespace exists.
- Failed to list iceberg tables.
- Loading uncommitted table is not supported!
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/e36213ddcd84f202.
Report an issue: GitHub.