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

Failed to check namespace exists.

Error message

Failed to check namespace exists.

What it means

`JniCatalog::namespace_exists` performs an existence check through the JVM catalog via JNI. Failures of the JNI call, Java-side exception, or response parsing are wrapped as an iceberg `Unexpected` error with the message 'Failed to check namespace exists.' and the underlying error as source.

Source

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

    async fn namespace_exists(&self, namespace: &NamespaceIdent) -> iceberg::Result<bool> {
        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);
                let namespace_jstr = env.new_string(&namespace_str).unwrap();

                let exists =
                    call_method!(env, inner.java_catalog.as_obj(), {boolean namespaceExists(String)},
                    &namespace_jstr)
                    .with_context(|| format!("Failed to check namespace exists: {namespace}"))?;

                Ok(exists)
            })
        })
        .await
        .map_err(|e| {
            iceberg::Error::new(
                iceberg::ErrorKind::Unexpected,
                "Failed to check namespace exists.",
            )
            .with_source(e)
        })
    }

    /// Drop a namespace from the catalog.
    async fn drop_namespace(&self, _namespace: &NamespaceIdent) -> iceberg::Result<()> {
        todo!()
    }

    /// List tables from namespace.
    async fn list_tables(&self, namespace: &NamespaceIdent) -> iceberg::Result<Vec<TableIdent>> {
        let inner = self.inner.clone();
        let namespace = namespace.clone();
        execute_blocking_jni(move || {
            execute_with_jni_env(inner.jvm, |env| {

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Inspect the attached source error for the root Java exception.
  2. Verify catalog endpoint, credentials and network connectivity.
  3. Ensure the JNI/JVM environment for the backend is properly installed.
  4. Retry after the catalog service recovers.
Defensive patterns

Strategy: retry

Validate before calling

// Verify catalog config keys (endpoint/credentials) are present before calls
fn catalog_config_ok(props: &serde_json::Value) -> bool {
    props.get("catalog.uri").is_some() && props.get("catalog.type").is_some()
}

Try / catch

match catalog.namespace_exists(&ns).await {
    Err(e) if e.kind() == iceberg::ErrorKind::Unexpected => {
        tracing::warn!(source = ?e.source(), "namespace_exists check failed; retrying with backoff");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling namespace_exists (directly or from CREATE SINK/TABLE validation) when the JNI/Java catalog call fails.

Common situations: Catalog service temporarily unavailable; bad credentials; missing Java classes on classpath; network partition to the catalog backend.

Related errors


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