risingwavelabs/risingwave · error · StreamExecutorError

Failed to decode prost: field not found `{}`

Error message

Failed to decode prost: field not found `{}`

What it means

This is the message produced when a PbFieldNotFound (a missing required protobuf field returned by generated prost decoders) is converted into StreamExecutorError. The From impl at src/stream/src/executor/error.rs:142 wraps it into an anyhow Uncategorized error with the text 'Failed to decode prost: field not found `{}`', where {} is the missing field's name.

Source

Thrown at src/stream/src/executor/error.rs:144

        Self::serde_error(m)
    }
}
impl From<ValueEncodingError> for StreamExecutorError {
    fn from(e: ValueEncodingError) -> Self {
        Self::serde_error(e)
    }
}

/// Connector error.
impl From<ConnectorError> for StreamExecutorError {
    fn from(s: ConnectorError) -> Self {
        Self::connector_error(s)
    }
}

impl From<PbFieldNotFound> for StreamExecutorError {
    fn from(err: PbFieldNotFound) -> Self {
        Self::from(anyhow::anyhow!(
            "Failed to decode prost: field not found `{}`",
            err.0
        ))
    }
}

impl From<String> for StreamExecutorError {
    fn from(s: String) -> Self {
        ErrorKind::Uncategorized(anyhow::anyhow!(s)).into()
    }
}

impl From<(SinkError, SinkId)> for StreamExecutorError {
    fn from((err, sink_id): (SinkError, SinkId)) -> Self {
        ErrorKind::SinkError(err, sink_id).into()
    }
}

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Verify all nodes in the cluster run the same RisingWave version/proto definitions.
  2. Identify the missing field name from the message and check which proto message is being decoded.
  3. Regenerate/check the prost bindings if the schema was changed locally.
  4. If the payload is user-provided or external, validate it before decoding.

Example fix

// before (mixed cluster: compute node older than meta)
# risingwavecompute --version 1.x-old  ; meta sends new proto fields
// after
# upgrade compute nodes to the same version as meta so prost schemas match
Defensive patterns

Strategy: validation

Validate before calling

// check node versions match before mixed-cluster decoding
fn ensure_version_compatible(local: &str, peer: &str) -> Result<(), String> {
    if local != peer {
        return Err(format!("proto schema mismatch: local={local} peer={peer}"));
    }
    Ok(())
}

Type guard

fn is_prost_field_not_found(e: &StreamExecutorError) -> bool {
    e.to_string().starts_with("Failed to decode prost: field not found")
}

Try / catch

if let Err(e) = decode_result {
    if e.to_string().contains("Failed to decode prost: field not found") {
        tracing::error!(error = %e, "protobuf schema mismatch between nodes");
        return Err(e);
    }
    return Err(e);
}

Prevention

When it happens

Trigger: Raised in `From<PbFieldNotFound>::from` when a prost-decoded protobuf message (e.g. a StreamChunk, barrier, or actor message arriving over the exchange) lacks a field the Rust type marks as required (prost's `#[prost(..., required)]` / oneof decoding).

Common situations: Proto schema drift between nodes (one node compiled with a newer .proto than another); corrupted or truncated message payloads; incompatibility between meta/compute/frontend versions in a mixed cluster.

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/50fb455e41ae00ca. Report an issue: GitHub.