risingwavelabs/risingwave · error

Input object is not a java string and can't be converted!

Error message

Input object is not a java string and can't be converted!

What it means

jobj_to_str converts a returned Java object to a Rust String but first verifies the object is an instance of java/lang/String. If it is not, it bails with this error instead of attempting an unsafe cast. It guards JNI calls whose Java methods are expected to return strings (namespace/table names, exception messages).

Solutions

  1. Ensure the connector/iceberg jars in CONNECTOR_LIBS_PATH match the versions RisingWave expects (risingwave-source-cdc first on classpath).
  2. Inspect the Java method being called and confirm its return type is String.
  3. Check whether the returned object is null/None from the Java side and handle it before conversion.
  4. Update or reinstall the connector package to fix signature drift.

Example fix

// before (java side)
public Object listTables() { return tablesList; } // returns List, not String
// after (java side)
public String listTables() { return serialize(tablesList); }
Defensive patterns

Strategy: try-catch

Validate before calling

// verify expected jar version is on the classpath
ls "$CONNECTOR_LIBS_PATH" | grep -q 'risingwave-connector' && echo ok || echo 'connector jars missing or outdated'

Try / catch

match catalog.list_tables() {
    Err(e) if e.to_string().contains("not a java string") => {
        // suspect jar version mismatch or null return; refresh jars and retry
    }
    other => other?,
}

Prevention

When it happens

Trigger: A Java method invoked via list_namespaces, list_tables, create_table, load_table, update_table, or execute_with_jni_env returns a non-String object where a String was expected, e.g. a patched/incorrect Debezium-Iceberg jar returning a different type.

Common situations: Mismatched jar versions where the Java method signature changed and now returns an array or custom type, a null object being returned by the Java side, using an outdated or hand-patched connector jar.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at src/jni_core/src/jvm_runtime.rs:270

            let message = call_method!(env, exception, {String getMessage()})?;
            let message = jobj_to_str(&mut env, message)?;
            return Err(anyhow::anyhow!("Caught Java Exception: {}", message));
        }
        Ok(false) => {
            // No exception, do nothing
        }
        Err(e) => {
            tracing::warn!(error = %e.as_report(), "Failed to check exception");
        }
    }

    ret
}

/// A helper method to convert an java object to rust string.
pub fn jobj_to_str(env: &mut JNIEnv<'_>, obj: JObject<'_>) -> anyhow::Result<String> {
    if !env.is_instance_of(&obj, "java/lang/String")? {
        bail!("Input object is not a java string and can't be converted!")
    }
    let jstr = JString::from(obj);
    let java_str = env.get_string(&jstr)?;
    Ok(java_str.to_str()?.to_owned())
}

/// Dumps the JVM stack traces.
///
/// # Returns
///
/// - `Ok(None)` if JVM is not initialized.
/// - `Ok(Some(String))` if JVM is initialized and stack traces are dumped.
/// - `Err` if failed to dump stack traces.
pub fn dump_jvm_stack_traces() -> anyhow::Result<Option<String>> {
    match Jvm::get() {
        None => Ok(None),
        Some(jvm) => execute_with_jni_env(jvm, |env| {
            let result = call_static_method!(

View on GitHub (pinned to 6469eb736d)