{"record":{"id":"f251580a3b6317d9","repo":"risingwavelabs/risingwave","slug":"anyhow-err-msg","errorCode":null,"errorMessage":"anyhow!(err_msg)","messagePattern":"anyhow!\\(err_msg\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/jni_core/src/lib.rs","lineNumber":1109,"sourceCode":"                tracing::info!(error = %e.as_report(), \"send error\");\n                Ok(JNI_FALSE)\n            }\n        }\n    })\n}\n\n#[unsafe(no_mangle)]\nextern \"system\" fn Java_com_risingwave_java_binding_Binding_sendCdcSourceErrorToChannel<'a>(\n    env: EnvParam<'a>,\n    channel: Pointer<'a, JniSenderType<GetEventStreamResponse>>,\n    msg: JString<'a>,\n) -> jboolean {\n    execute_and_catch(env, move |env| {\n        let ret = env.get_string(&msg);\n        match ret {\n            Ok(str) => {\n                let err_msg: String = str.into();\n                match channel.as_ref().blocking_send(Err(anyhow!(err_msg))) {\n                    Ok(_) => Ok(JNI_TRUE),\n                    Err(e) => {\n                        tracing::info!(error = ?e.as_report(), \"send error\");\n                        Ok(JNI_FALSE)\n                    }\n                }\n            }\n            Err(err) => {\n                if msg.is_null() {\n                    tracing::warn!(\"source error message is null\");\n                    Ok(JNI_TRUE)\n                } else {\n                    tracing::error!(error = ?err.as_report(), \"source error message should be a java string\");\n                    Ok(JNI_FALSE)\n                }\n            }\n        }\n    })","sourceCodeStart":1091,"sourceCodeEnd":1127,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/jni_core/src/lib.rs#L1091-L1127","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nreceiver.close(); // then Java sends error -> blocking_send fails\n// after\n// keep receiver alive until source is fully stopped, then drop it\nlet resp = rx.recv().await; // consume the Err(anyhow!(msg)) payload","handlingStrategy":"try-catch","validationCode":"// Java, before sending\nif (channelPtr == 0) return; // channel already closed on the Rust side\nif (msg == null) msg = \"unknown cdc source error\";","typeGuard":null,"tryCatchPattern":"boolean ok = Binding.sendCdcSourceErrorToChannel(channelPtr, msg);\nif (!ok) {\n    // channel closed: Rust receiver dropped; fall back to local logging\n    log.warn(\"failed to relay source error to rust: \" + msg);\n}","preventionTips":["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"],"tags":["cdc","channel","jni","error-propagation"],"backgroundTag":"broken-pipe","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}