linera-io/linera-protocol · error · GrpcProtoConversionError

InconsistentChainId

InconsistentChainId

Error message

GrpcProtoConversionError::InconsistentChainId

What it means

Converting a gRPC api::BlockProposal into the internal BlockProposal deserializes the signed ProposalContent and cross-checks that its inner block.chain_id matches the chain_id field on the protobuf envelope. GrpcProtoConversionError::InconsistentChainId means those two identifiers disagree, so the message is malformed or tampered with.

Source

Thrown at linera-rpc/src/grpc/conversions.rs:272

        Ok(Self {
            chain_id: Some(block_proposal.content.block.chain_id.into()),
            content: bincode::serialize(&block_proposal.content)?,
            owner: Some(block_proposal.owner().try_into()?),
            signature: Some(block_proposal.signature.into()),
            original_proposal: block_proposal
                .original_proposal
                .map(|cert| bincode::serialize(&cert))
                .transpose()?,
        })
    }
}

impl TryFrom<api::BlockProposal> for BlockProposal {
    type Error = GrpcProtoConversionError;

    fn try_from(block_proposal: api::BlockProposal) -> Result<Self, Self::Error> {
        let content: ProposalContent = bincode::deserialize(&block_proposal.content)?;
        ensure!(
            Some(content.block.chain_id.into()) == block_proposal.chain_id,
            GrpcProtoConversionError::InconsistentChainId
        );
        Ok(Self {
            content,
            signature: try_proto_convert(block_proposal.signature)?,
            original_proposal: block_proposal
                .original_proposal
                .map(|bytes| bincode::deserialize(&bytes))
                .transpose()?,
        })
    }
}

impl TryFrom<api::CrossChainRequest> for CrossChainRequest {
    type Error = GrpcProtoConversionError;

    fn try_from(cross_chain_request: api::CrossChainRequest) -> Result<Self, Self::Error> {

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Drop the message and ignore or penalize the sender — the proposal cannot be validated as-is
  2. If you control the sender, derive the envelope chain_id from the same serialized content it ships (content.block.chain_id)
  3. Pin all Linera components (client, validator, proxy) to one release

Example fix

// before
let proposal: BlockProposal = api_block_proposal.try_into()?; // aborts handler on InconsistentChainId

// after
let proposal = match api_block_proposal.try_into() {
    Ok(p) => p,
    Err(GrpcProtoConversionError::InconsistentChainId) => {
        tracing::warn!("dropping block proposal with mismatched chain_id");
        return Ok(api::BlockProposalResponse::default()); // reject, keep serving
    }
    Err(e) => return Err(e.into()),
};
Defensive patterns

Strategy: try-catch

Validate before calling

let content: ProposalContent = bincode::deserialize(&raw.content)?;
if Some(content.block.chain_id.into()) != raw.chain_id {
    // drop the message before attempting full conversion
}

Type guard

fn proposal_chain_ids_match(raw: &api::BlockProposal) -> bool {
    bincode::deserialize::<ProposalContent>(&raw.content)
        .map(|c| Some(c.block.chain_id.into()) == raw.chain_id)
        .unwrap_or(false)
}

Try / catch

Match GrpcProtoConversionError::InconsistentChainId specifically and treat the message as invalid input: log the mismatched identifiers, do not retry the conversion, and keep serving other peers.

Prevention

When it happens

Trigger: A validator, proxy, or client receives a BlockProposal whose top-level chain_id was set independently of the bincode-encoded content — a forwarding bug that rewrites chain_id, version-skewed serializers, or a crafted proposal.

Common situations: Client, validator, and proxy built from different linera-rpc versions; a relay mislabeling forwarded proposals; adversarial nodes sending a proposal for one chain under another chain's id.

Related errors


AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22). Data as JSON: /api/errors/3ff79aa78f87d8e0. Report an issue: GitHub.