risingwavelabs/risingwave · error · BindingError::Decode

DecodeError {error}

Error message

DecodeError {error}

What it means

BindingError::Decode wraps a prost/prost-derived DecodeError produced while decoding protobuf bytes passed from Java into RisingWave internal messages (e.g. StreamChunk, rows, Watch response payloads). Shown as 'DecodeError {error}'. It means the byte payload crossing the JNI boundary is not a valid encoding of the expected protobuf message.

Source

Thrown at src/jni_core/src/lib.rs:98

    LazyLock::new(|| tokio::runtime::Runtime::new().unwrap());

#[derive(Error, Debug)]
pub enum BindingError {
    #[error("JniError {error}")]
    Jni {
        #[from]
        error: jni::errors::Error,
        backtrace: Backtrace,
    },

    #[error("StorageError {error}")]
    Storage {
        #[from]
        error: anyhow::Error,
        backtrace: Backtrace,
    },

    #[error("DecodeError {error}")]
    Decode {
        #[from]
        error: DecodeError,
        backtrace: Backtrace,
    },

    #[error("StreamChunkArrayError {error}")]
    StreamChunkArray {
        #[from]
        error: ArrayError,
        backtrace: Backtrace,
    },
}

type Result<T> = std::result::Result<T, BindingError>;

pub fn to_guarded_slice<'array, 'env>(
    array: &'array JByteArray<'env>,

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Verify the Java side serializes with the exact same generated protobuf class/version as the native binding was built with
  2. Dump the failing byte[] length and first bytes to confirm it is the expected wire format (not base64/compressed text)
  3. Regenerate the Java protobuf stubs from the same .proto files used to build risingwave_jni_core
  4. If version skew is expected, pin both the JAR and native library to the same RisingWave release

Example fix

// before
byte[] bytes = Base64.decode(payload); // DecodeError: invalid wire type
binding.next(bytes);
// after
byte[] bytes = payload.toByteArray(); // raw protobuf bytes from matching generated class
binding.next(bytes);
Defensive patterns

Strategy: validation

Validate before calling

// Java, before crossing the boundary
byte[] bytes = protoMsg.toByteArray(); // never base64/compressed text
if (bytes.length == 0) throw new IllegalStateException("empty protobuf payload");

Try / catch

try {
    binding.decode(bytes);
} catch (RuntimeException e) {
    if (e.getMessage().contains("DecodeError")) {
        // schema/version skew: regenerate stubs, verify byte source
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling JNI entry points that accept serialized protobuf payloads (byte[] containing StreamChunk, row encodings, etc.) where the bytes are truncated, corrupted, produced by a different schema version, or not protobuf at all.

Common situations: Java client built against an older protobuf schema than the native library (version skew); passing compressed or base64 text where raw protobuf bytes are expected; manually assembled byte arrays with wrong field ordering.

Understand the failure class

Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.

Related errors


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