risingwavelabs/risingwave · warning
anyhow!(err_msg)
Error message
anyhow!(err_msg)
What it means
In Java_com_risingwave_java_binding_Binding_sendCdcSourceErrorToChannel, a Java error message string is converted to a Rust String and wrapped with anyhow! before being sent as Err(...) over the JNI channel to the Rust consumer. The anyhow! here is the transport wrapper for the error payload — the message originates from the Java CDC connector and is delivered as an anyhow::Error to whoever receives from the channel. If the channel send itself fails, JNI_FALSE is returned and the error is logged.
Source
Thrown at src/jni_core/src/lib.rs:1109
tracing::info!(error = %e.as_report(), "send error");
Ok(JNI_FALSE)
}
}
})
}
#[unsafe(no_mangle)]
extern "system" fn Java_com_risingwave_java_binding_Binding_sendCdcSourceErrorToChannel<'a>(
env: EnvParam<'a>,
channel: Pointer<'a, JniSenderType<GetEventStreamResponse>>,
msg: JString<'a>,
) -> jboolean {
execute_and_catch(env, move |env| {
let ret = env.get_string(&msg);
match ret {
Ok(str) => {
let err_msg: String = str.into();
match channel.as_ref().blocking_send(Err(anyhow!(err_msg))) {
Ok(_) => Ok(JNI_TRUE),
Err(e) => {
tracing::info!(error = ?e.as_report(), "send error");
Ok(JNI_FALSE)
}
}
}
Err(err) => {
if msg.is_null() {
tracing::warn!("source error message is null");
Ok(JNI_TRUE)
} else {
tracing::error!(error = ?err.as_report(), "source error message should be a java string");
Ok(JNI_FALSE)
}
}
}
})View on GitHub (pinned to 6469eb736d)
Solutions
- Check JNI_TRUE/JNI_FALSE return value: FALSE means the channel was closed — the Rust consumer must keep the receiver alive until the source is torn down
- Inspect Rust logs for 'send error' to see why the relay failed
- Fix the underlying CDC source error in the Java message; the anyhow! payload itself is the diagnostic
- Ensure graceful shutdown ordering: stop the Java source before dropping the Rust receiver
Example fix
// before receiver.close(); // then Java sends error -> blocking_send fails // after // keep receiver alive until source is fully stopped, then drop it let resp = rx.recv().await; // consume the Err(anyhow!(msg)) payload
Defensive patterns
Strategy: try-catch
Validate before calling
// Java, before sending if (channelPtr == 0) return; // channel already closed on the Rust side if (msg == null) msg = "unknown cdc source error";
Try / catch
boolean ok = Binding.sendCdcSourceErrorToChannel(channelPtr, msg);
if (!ok) {
// channel closed: Rust receiver dropped; fall back to local logging
log.warn("failed to relay source error to rust: " + msg);
} Prevention
- Check the JNI_FALSE return and stop retrying sends on a closed channel
- Keep the Rust receiver alive until the Java source is fully stopped
- Include actionable context in the error string — it becomes the anyhow message in Rust
- Order teardown: stop source, drain channel, drop receiver
When it happens
Trigger: Java code calls sendCdcSourceErrorToChannel(channelPointer, msg) to propagate a CDC source error into Rust; the msg string is converted and injected into the channel. Returns false only when the tokio channel is closed/full on the Rust side.
Common situations: Rust side dropped the GetEventStreamResponse receiver while Java still reports a source error; blocking_send fails during shutdown; a CDC source (Kafka/Debezium) failed and the error is being relayed.
Related errors
- source validation failed
- all senders are dropped
- broken broadcast_channel
- broken hash_shuffle_channel
- broken fifo_channel
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/f251580a3b6317d9.
Report an issue: GitHub.