{"record":{"id":"47f0242356896f00","repo":"FuelLabs/fuel-core","slug":"could-not-convert-storage-slot-value-to-bytes32","errorCode":null,"errorMessage":"Could not convert storage slot value to Bytes32: {}","messagePattern":"Could not convert storage slot value to Bytes32: (.+?)","errorType":"validation","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":98,"sourceCode":"    let block_height = proto.block_height.into();\n    #[allow(clippy::useless_conversion)]\n    let tx_index = proto.tx_index.try_into().map_err(|e| {\n        Error::Serialization(anyhow!(\"Could not convert tx_index to target type: {}\", e))\n    })?;\n    Ok(TxPointer::new(block_height, tx_index))\n}\n\nfn storage_slot_from_proto(\n    proto: &ProtoStorageSlot,\n) -> crate::result::Result<StorageSlot> {\n    let key = Bytes32::try_from(proto.key.as_slice()).map_err(|e| {\n        Error::Serialization(anyhow!(\n            \"Could not convert storage slot key to Bytes32: {}\",\n            e\n        ))\n    })?;\n    let value = Bytes32::try_from(proto.value.as_slice()).map_err(|e| {\n        Error::Serialization(anyhow!(\n            \"Could not convert storage slot value to Bytes32: {}\",\n            e\n        ))\n    })?;\n    Ok(StorageSlot::new(key, value))\n}\n\nfn contract_input_from_proto(\n    proto: &ProtoContractInput,\n) -> crate::result::Result<fuel_core_types::fuel_tx::input::contract::Contract> {\n    let utxo_proto = proto.utxo_id.as_ref().ok_or_else(|| {\n        Error::Serialization(anyhow!(\"Missing utxo_id on contract input\"))\n    })?;\n    let utxo_id = utxo_id_from_proto(utxo_proto)?;\n    let balance_root = Bytes32::try_from(proto.balance_root.as_slice()).map_err(|e| {\n        Error::Serialization(anyhow!(\"Could not convert balance_root to Bytes32: {}\", e))\n    })?;\n    let state_root = Bytes32::try_from(proto.state_root.as_slice()).map_err(|e| {","sourceCodeStart":80,"sourceCodeEnd":116,"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#L80-L116","documentation":"Thrown by storage_slot_from_proto when the proto storage slot's value field cannot be converted: Bytes32::try_from only accepts exactly 32 bytes, and proto.value has a different length. It is wrapped as Error::Serialization and fails the slot, the containing Create transaction, and the block decode.","triggerScenarios":"fuel_block_from_protobuf on a block where some ProtoStorageSlot.value is empty or any non-32 length - corrupted blob, truncated frame, or a producer writing variable-length bytes for a fixed 32-byte field.","commonSituations":"Version-incompatible encoder; corruption on disk or in transit; test data with arbitrary-length byte vectors.","solutions":["Log the actual value length of the failing slot to confirm the mismatch.","Validate slot.key and slot.value are both 32 bytes before decoding; reject the block early with slot position in the error.","Align producer and consumer fuel-core versions so storage slot values are always 32 bytes.","Re-fetch the block from a healthy peer or re-encode from canonical on-chain data."],"exampleFix":"// before\nlet slot = storage_slot_from_proto(proto_slot)?;\n\n// after\nif proto_slot.value.len() != 32 {\n    return Err(Error::Serialization(anyhow::anyhow!(\n        \"storage slot value has {} bytes; expected 32\",\n        proto_slot.value.len()\n    )));\n}\nlet slot = storage_slot_from_proto(proto_slot)?;","handlingStrategy":"validation","validationCode":"fn storage_slot_value_valid(slot: &ProtoStorageSlot) -> bool {\n    slot.value.len() == 32\n}","typeGuard":"fn is_bytes32(b: &[u8]) -> bool { b.len() == 32 }","tryCatchPattern":"match storage_slot_from_proto(slot) {\n    Ok(s) => slots.push(s),\n    Err(Error::Serialization(ctx)) if ctx.to_string().contains(\"storage slot value\") => {\n        tracing::warn!(value_len = slot.value.len(), \"rejecting malformed storage slot\");\n        return Err(Error::Serialization(ctx));\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Validate both key and value lengths (32 bytes) for every storage slot before decoding.","Use version-compatible encoders; re-encode from canonical on-chain data when in doubt.","Roundtrip-test encoded blocks after any fuel-core upgrade."],"tags":["rust","fuel-core","protobuf","deserialization","bytes32","storage-slot"],"backgroundTag":null,"analyzedSha":"b9d4d170da3a31c9ace5f963d633b326348e0d42","analyzedAt":"2026-08-16T08:56:42.692Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}