{"record":{"id":"33ea54750751c02a","repo":"FuelLabs/fuel-core","slug":"could-not-convert-owner-to-address","errorCode":null,"errorMessage":"Could not convert owner to Address: {}","messagePattern":"Could not convert owner to Address: (.+?)","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":874,"sourceCode":"    }\n}\n\nfn input_from_proto_input(proto_input: &ProtoInput) -> crate::result::Result<Input> {\n    let variant = proto_input\n        .variant\n        .as_ref()\n        .ok_or_else(|| Error::Serialization(anyhow!(\"Missing input variant\")))?;\n\n    match variant {\n        ProtoInputVariant::CoinSigned(proto_coin_signed) => {\n            let utxo_proto = proto_coin_signed\n                .utxo_id\n                .as_ref()\n                .ok_or_else(|| Error::Serialization(anyhow!(\"Missing utxo_id\")))?;\n            let utxo_id = utxo_id_from_proto(utxo_proto)?;\n            let owner =\n                Address::try_from(proto_coin_signed.owner.as_slice()).map_err(|e| {\n                    Error::Serialization(anyhow!(\n                        \"Could not convert owner to Address: {}\",\n                        e\n                    ))\n                })?;\n            let asset_id = fuel_core_types::fuel_types::AssetId::try_from(\n                proto_coin_signed.asset_id.as_slice(),\n            )\n            .map_err(|e| Error::Serialization(anyhow!(e)))?;\n            let tx_pointer_proto = proto_coin_signed\n                .tx_pointer\n                .as_ref()\n                .ok_or_else(|| Error::Serialization(anyhow!(\"Missing tx_pointer\")))?;\n            let tx_pointer = tx_pointer_from_proto(tx_pointer_proto)?;\n            let witness_index =\n                u16::try_from(proto_coin_signed.witness_index).map_err(|e| {\n                    Error::Serialization(anyhow!(\n                        \"Could not convert witness_index to u16: {}\",\n                        e","sourceCodeStart":856,"sourceCodeEnd":892,"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#L856-L892","documentation":"For a CoinSigned input, the owner bytes must convert to fuel_types::Address, a fixed 32-byte type. Address::try_from fails on any length other than 32 (including the empty default when the producer never set owner), and the failure is wrapped as 'Could not convert owner to Address: {e}'.","triggerScenarios":"CoinSigned input with owner field unset (0 bytes — prost default) or wrong length (e.g., 20-byte EVM-style address, 64-byte key). The underlying try_from error is chained in the message.","commonSituations":"Producer omitted owner; address encoded from another ecosystem with different width; truncated payloads; test fixtures with placeholder addresses.","solutions":["Validate owner.len() == 32 on every coin input before running the conversion","Fix the producer to serialize the full 32-byte Fuel Address","If the source uses another address format, convert it explicitly at the boundary (e.g., left-pad/hash) rather than passing raw bytes","Include the failing input's index and actual length in your validation logs to speed up producer-side fixes"],"exampleFix":"// before\nlet owner = Address::try_from(proto_coin_signed.owner.as_slice()).map_err(...)?;\n\n// after\nconst ADDR_LEN: usize = 32;\nif proto_coin_signed.owner.len() != ADDR_LEN {\n    return Err(anyhow!(\"coin owner len {} != {ADDR_LEN}\", proto_coin_signed.owner.len()));\n}\nlet owner = Address::try_from(proto_coin_signed.owner.as_slice()).map_err(...)?;","handlingStrategy":"validation","validationCode":"fn owner_is_valid_address(c: &ProtoCoinSigned) -> bool { c.owner.len() == 32 }","typeGuard":"fn is_fuel_address(b: &[u8]) -> bool { b.len() == 32 }","tryCatchPattern":"let owner = Address::try_from(c.owner.as_slice())\n    .with_context(|| format!(\"owner len {} (expected 32)\", c.owner.len()))?;","preventionTips":["Check fixed widths (32 bytes) before try_from on every address-like field","Convert foreign address formats at the ingestion boundary, never implicitly","Fail loudly in producer unit tests when addresses are not 32 bytes"],"tags":["rust","fuel","protobuf","serialization","coin-input","address","validation"],"backgroundTag":null,"analyzedSha":"b9d4d170da3a31c9ace5f963d633b326348e0d42","analyzedAt":"2026-08-16T08:56:42.692Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}