{"record":{"id":"3ff79aa78f87d8e0","repo":"linera-io/linera-protocol","slug":"inconsistentchainid","errorCode":"InconsistentChainId","errorMessage":"GrpcProtoConversionError::InconsistentChainId","messagePattern":"GrpcProtoConversionError::InconsistentChainId","errorType":"exception","errorClass":"GrpcProtoConversionError","httpStatus":null,"severity":"error","filePath":"linera-rpc/src/grpc/conversions.rs","lineNumber":272,"sourceCode":"        Ok(Self {\n            chain_id: Some(block_proposal.content.block.chain_id.into()),\n            content: bincode::serialize(&block_proposal.content)?,\n            owner: Some(block_proposal.owner().try_into()?),\n            signature: Some(block_proposal.signature.into()),\n            original_proposal: block_proposal\n                .original_proposal\n                .map(|cert| bincode::serialize(&cert))\n                .transpose()?,\n        })\n    }\n}\n\nimpl TryFrom<api::BlockProposal> for BlockProposal {\n    type Error = GrpcProtoConversionError;\n\n    fn try_from(block_proposal: api::BlockProposal) -> Result<Self, Self::Error> {\n        let content: ProposalContent = bincode::deserialize(&block_proposal.content)?;\n        ensure!(\n            Some(content.block.chain_id.into()) == block_proposal.chain_id,\n            GrpcProtoConversionError::InconsistentChainId\n        );\n        Ok(Self {\n            content,\n            signature: try_proto_convert(block_proposal.signature)?,\n            original_proposal: block_proposal\n                .original_proposal\n                .map(|bytes| bincode::deserialize(&bytes))\n                .transpose()?,\n        })\n    }\n}\n\nimpl TryFrom<api::CrossChainRequest> for CrossChainRequest {\n    type Error = GrpcProtoConversionError;\n\n    fn try_from(cross_chain_request: api::CrossChainRequest) -> Result<Self, Self::Error> {","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/linera-io/linera-protocol/blob/6c226ddcb332ef55118dc8d0aafbd093d5420899/linera-rpc/src/grpc/conversions.rs#L254-L290","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Drop the message and ignore or penalize the sender — the proposal cannot be validated as-is","If you control the sender, derive the envelope chain_id from the same serialized content it ships (content.block.chain_id)","Pin all Linera components (client, validator, proxy) to one release"],"exampleFix":"// before\nlet proposal: BlockProposal = api_block_proposal.try_into()?; // aborts handler on InconsistentChainId\n\n// after\nlet proposal = match api_block_proposal.try_into() {\n    Ok(p) => p,\n    Err(GrpcProtoConversionError::InconsistentChainId) => {\n        tracing::warn!(\"dropping block proposal with mismatched chain_id\");\n        return Ok(api::BlockProposalResponse::default()); // reject, keep serving\n    }\n    Err(e) => return Err(e.into()),\n};","handlingStrategy":"try-catch","validationCode":"let content: ProposalContent = bincode::deserialize(&raw.content)?;\nif Some(content.block.chain_id.into()) != raw.chain_id {\n    // drop the message before attempting full conversion\n}","typeGuard":"fn proposal_chain_ids_match(raw: &api::BlockProposal) -> bool {\n    bincode::deserialize::<ProposalContent>(&raw.content)\n        .map(|c| Some(c.block.chain_id.into()) == raw.chain_id)\n        .unwrap_or(false)\n}","tryCatchPattern":"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.","preventionTips":["Always derive the envelope chain_id from the serialized content; never set it separately","Pin all Linera components to one release when proxies forward proposals","Treat conversion failures as adversarial input in alerting, not transient errors"],"tags":["grpc","protocol-validation","block-proposal","chain-id","linera-rpc"],"backgroundTag":"chain-id-mismatch","analyzedSha":"6c226ddcb332ef55118dc8d0aafbd093d5420899","analyzedAt":"2026-08-22T22:49:09.787Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}