{"record":{"id":"282df942b124d8f4","repo":"risingwavelabs/risingwave","slug":"failed-to-check-iceberg-table-exists","errorCode":null,"errorMessage":"Failed to check iceberg table exists.","messagePattern":"Failed to check iceberg table exists\\.","errorType":"exception","errorClass":"iceberg::Error (ErrorKind::Unexpected)","httpStatus":null,"severity":"error","filePath":"src/connector/src/connector_common/iceberg/jni_catalog.rs","lineNumber":467,"sourceCode":"        execute_blocking_jni(move || {\n            execute_with_jni_env(inner.jvm, |env| {\n                let table_name_str = table.to_string();\n\n                let table_name_jstr = env.new_string(&table_name_str).unwrap();\n\n                let exists =\n                    call_method!(env, inner.java_catalog.as_obj(), {boolean tableExists(String)},\n                    &table_name_jstr)\n                    .with_context(|| {\n                        format!(\"Failed to check iceberg table exists: {table_name_str}\")\n                    })?;\n\n                Ok(exists)\n            })\n        })\n        .await\n        .map_err(|e| {\n            iceberg::Error::new(\n                iceberg::ErrorKind::Unexpected,\n                \"Failed to check iceberg table exists.\",\n            )\n            .with_source(e)\n        })\n    }\n\n    /// Rename a table in the catalog.\n    async fn rename_table(&self, _src: &TableIdent, _dest: &TableIdent) -> iceberg::Result<()> {\n        todo!()\n    }\n\n    /// Update a table to the catalog.\n    async fn update_table(&self, mut commit: TableCommit) -> iceberg::Result<Table> {\n        let inner = self.inner.clone();\n        let file_io_props = self.file_io_props.clone();\n        let runtime = Runtime::try_current()?;\n        execute_blocking_jni(move || {","sourceCodeStart":449,"sourceCodeEnd":485,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/connector_common/iceberg/jni_catalog.rs#L449-L485","documentation":"JniCatalog::table_exists wraps failures from the JNI existence-check call into this Unexpected iceberg error with the underlying error attached. This is not a 'table does not exist' result — that returns Ok(false); this error means the check itself failed.","triggerScenarios":"The JNI/Java catalog tableExists call errors out inside the block_in_place task: Java exception (auth, connectivity, invalid identifier), JNIEnv failure, or a JoinError from a panicked closure.","commonSituations":"Backend catalog temporarily unreachable during existence probes; malformed TableIdent rejected by the Java catalog; JVM/classpath misconfiguration when RisingWave validates an Iceberg table reference.","solutions":["Read the with_source error chain for the actual Java exception","Validate the TableIdent (namespace + table name) matches what exists in the backend","Check JVM initialization and classpath","Retry on transient backend connectivity failures"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Validate identifier before existence probe\ndebug_assert!(!ident.name().is_empty(), \"table name required\");","typeGuard":"fn is_jni_exists_failure(err: &iceberg::Error) -> bool {\n    err.kind() == iceberg::ErrorKind::Unexpected && err.message().contains(\"Failed to check iceberg table exists.\")\n}","tryCatchPattern":"let exists = loop {\n    match catalog.table_exists(&ident).await {\n        Ok(v) => break v,\n        Err(e) if is_transient(&e) => continue, // backoff\n        Err(e) => return Err(e),\n    }\n};","preventionTips":["Retry existence checks on transient backend errors","Validate TableIdent format before the JNI call","Ensure JVM health-checks run before catalog operations"],"tags":["iceberg","jni","catalog","table-exists"],"backgroundTag":"api-request-failed","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}