{"record":{"id":"ac5d3e5b3ae8a01b","repo":"FuelLabs/fuel-core","slug":"could-not-convert-message-digest-to-bytes32","errorCode":null,"errorMessage":"Could not convert message digest to Bytes32: {}","messagePattern":"Could not convert message digest to Bytes32: (.+?)","errorType":"exception","errorClass":"Error::Serialization","httpStatus":null,"severity":"error","filePath":"crates/services/block_aggregator_api/src/blocks/old_block_source/convertor_adapter/proto_to_fuel_conversions.rs","lineNumber":455,"sourceCode":"        ProtoReceiptVariant::ScriptResult(result) => {\n            let script_result = result.result.as_ref().ok_or_else(|| {\n                Error::Serialization(anyhow!(\"Missing script result payload\"))\n            })?;\n            let execution_result = script_execution_result_from_proto(script_result)?;\n            Ok(FuelReceipt::script_result(\n                execution_result,\n                result.gas_used,\n            ))\n        }\n        ProtoReceiptVariant::MessageOut(msg) => {\n            let sender = Address::try_from(msg.sender.as_slice())\n                .map_err(|e| Error::Serialization(anyhow!(e)))?;\n            let recipient = Address::try_from(msg.recipient.as_slice())\n                .map_err(|e| Error::Serialization(anyhow!(e)))?;\n            let nonce = Nonce::try_from(msg.nonce.as_slice())\n                .map_err(|e| Error::Serialization(anyhow!(e)))?;\n            let digest = Bytes32::try_from(msg.digest.as_slice()).map_err(|e| {\n                Error::Serialization(anyhow!(\n                    \"Could not convert message digest to Bytes32: {}\",\n                    e\n                ))\n            })?;\n            Ok(FuelReceipt::message_out_with_len(\n                sender,\n                recipient,\n                msg.amount,\n                nonce,\n                msg.len,\n                digest,\n                msg.data.clone(),\n            ))\n        }\n        ProtoReceiptVariant::Mint(mint) => {\n            let sub_id = SubAssetId::try_from(mint.sub_id.as_slice())\n                .map_err(|e| Error::Serialization(anyhow!(e)))?;\n            let contract_id = ContractId::try_from(mint.contract_id.as_slice())","sourceCodeStart":437,"sourceCodeEnd":473,"githubUrl":"https://github.com/FuelLabs/fuel-core/blob/b9d4d170da3a31c9ace5f963d633b326348e0d42/crates/services/block_aggregator_api/src/blocks/old_block_source/convertor_adapter/proto_to_fuel_conversions.rs#L437-L473","documentation":"Thrown while decoding a MessageOut receipt: the digest bytes field must be exactly 32 bytes for Bytes32; any other length fails try_from and is wrapped as Error::Serialization. The error fails the receipt, its transaction, and the block conversion.","triggerScenarios":"fuel_block_from_protobuf on a block where a MessageOut receipt's digest is empty or not 32 bytes - corrupted blob, truncated frame, or variable-length encoding by the producer.","commonSituations":"Producer/consumer version mismatch; corruption in transit or storage; test fixtures with arbitrary digests.","solutions":["Log the digest length of the failing MessageOut receipt.","Pre-validate len == 32 for MessageOut digest before decoding.","Align fuel-core versions on both ends.","Reject and re-fetch the block."],"exampleFix":"// before\nlet digest = Bytes32::try_from(msg.digest.as_slice()).map_err(|e| {\n    Error::Serialization(anyhow!(\"Could not convert message digest to Bytes32: {}\", e))\n})?;\n\n// after\nif msg.digest.len() != 32 {\n    return Err(Error::Serialization(anyhow::anyhow!(\n        \"MessageOut digest length {} != 32\", msg.digest.len()\n    )));\n}","handlingStrategy":"validation","validationCode":"fn message_out_digest_valid(msg: &ProtoMessageOut) -> bool {\n    msg.digest.len() == 32\n}","typeGuard":"fn is_bytes32(b: &[u8]) -> bool { b.len() == 32 }","tryCatchPattern":"match receipt_from_proto(r) {\n    Ok(receipt) => out.push(receipt),\n    Err(Error::Serialization(ctx)) if ctx.to_string().contains(\"message digest\") => {\n        tracing::warn!(len = msg.digest.len(), \"rejecting MessageOut with bad digest\");\n        return Err(Error::Serialization(ctx));\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Validate MessageOut digest length (32) together with the other digest fields.","Use canonical fuel-core encoders; version-pin peers.","Checksum payloads to detect corruption before decode."],"tags":["rust","fuel-core","protobuf","deserialization","bytes32","receipts"],"backgroundTag":null,"analyzedSha":"b9d4d170da3a31c9ace5f963d633b326348e0d42","analyzedAt":"2026-08-16T08:56:42.692Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}