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

Failed to list iceberg namespaces.

Error message

Failed to list iceberg namespaces.

What it means

`JniCatalog::list_namespaces` delegates the namespace listing to a JVM catalog via JNI and awaits the result on a Tokio runtime. Any failure of the JNI call, the Java-side request, or the response parsing is wrapped as an iceberg `Unexpected` error with the message 'Failed to list iceberg namespaces.' and the original error attached as source.

Source

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

        _parent: Option<&NamespaceIdent>,
    ) -> iceberg::Result<Vec<NamespaceIdent>> {
        let inner = self.inner.clone();
        execute_blocking_jni(move || {
            execute_with_jni_env(inner.jvm, |env| {
                let result_json =
                    call_method!(env, inner.java_catalog.as_obj(), {String listNamespaces()})
                        .with_context(|| "Failed to list iceberg namespaces".to_owned())?;

                let rust_json_str = jobj_to_str(env, result_json)?;

                let resp: ListNamespacesResponse = serde_json::from_str(&rust_json_str)?;

                Ok(resp.namespaces)
            })
        })
        .await
        .map_err(|e| {
            iceberg::Error::new(
                iceberg::ErrorKind::Unexpected,
                "Failed to list iceberg namespaces.",
            )
            .with_source(e)
        })
    }

    /// Create a new namespace inside the catalog.
    async fn create_namespace(
        &self,
        namespace: &iceberg::NamespaceIdent,
        _properties: HashMap<String, String>,
    ) -> iceberg::Result<iceberg::Namespace> {
        let inner = self.inner.clone();
        let namespace = namespace.clone();
        execute_blocking_jni(move || {
            execute_with_jni_env(inner.jvm, |env| {
                let namespace_str = namespace_to_string(&namespace);

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Inspect the wrapped source error (`with_source`) for the underlying Java exception.
  2. Verify catalog credentials, endpoint and region in the connection config.
  3. Ensure the JVM classpath/JNI runtime is correctly provisioned for the chosen catalog backend.
  4. Retry once the catalog service is reachable.
Defensive patterns

Strategy: retry

Validate before calling

// Before listing namespaces, probe catalog connectivity (e.g. HTTP HEAD for REST catalogs)
// and verify JVM/JNI classpath is present.
async fn catalog_reachable(endpoint: &str) -> bool {
    reqwest::Client::new().head(endpoint).send().await.map(|r| r.status().is_success()).unwrap_or(false)
}

Try / catch

// Rust: unwrap the iceberg error chain to log the Java cause
match catalog.list_namespaces(ns).await {
    Err(e) if e.kind() == iceberg::ErrorKind::Unexpected => {
        tracing::error!(source = ?e.source(), "JNI list_namespaces failed; check catalog service/JVM setup");
        // backoff and retry
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling list_namespaces on a JNI-backed Iceberg catalog when the JVM call fails (Java exception, IPC failure, malformed response JSON).

Common situations: Iceberg catalog backend (Glue/Hadoop/REST via Java) unreachable or misconfigured; missing JVM/JNI classes on the classpath; authentication failure against the catalog service.

Related errors


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