{"record":{"id":"085ea1eba6df6870","repo":"FuelLabs/fuel-core","slug":"missing-utxo-id","errorCode":null,"errorMessage":"Missing utxo_id","messagePattern":"Missing utxo_id","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":870,"sourceCode":"                FuelTransaction::blob(body, policies, inputs, outputs, witnesses);\n\n            Ok(FuelTransaction::Blob(blob_tx))\n        }\n    }\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 =","sourceCodeStart":852,"sourceCodeEnd":888,"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#L852-L888","documentation":"Inside the CoinSigned input variant, utxo_id is a nested proto message (not a plain field), so prost makes it optional. If it is None the convertor cannot build the UtxoId and raises 'Missing utxo_id' before constructing Input::coin_signed.","triggerScenarios":"A CoinSigned input proto where the utxo_id submessage was never attached — partial encoders, version skew where utxo_id changed shape, or hand-built test inputs.","commonSituations":"Default-constructed input structs; a producer that fills owner/amount but forgets the nested utxo_id; importing blocks encoded by an older client.","solutions":["Fix the producer to set utxo_id (tx_id + output_index) on every coin input it serializes","Pre-validate coin inputs: variant-specific required submessages (utxo_id, tx_pointer) must be Some","Align proto versions between the block source and this crate","Quarantine transactions with incomplete coin inputs and request re-encoding from source"],"exampleFix":"// before\nlet utxo_proto = proto_coin_signed.utxo_id.as_ref().ok_or_else(|| Error::Serialization(anyhow!(\"Missing utxo_id\")))?;\n\n// after (producer side)\nlet input = ProtoInput {\n    variant: Some(ProtoInputVariant::CoinSigned(ProtoCoinSigned {\n        utxo_id: Some(ProtoUtxoId { tx_id: tx_id_bytes, output_index: 0 }),\n        ..Default::default()\n    })),\n};","handlingStrategy":"validation","validationCode":"fn coin_signed_is_complete(c: &ProtoCoinSigned) -> bool {\n    c.utxo_id.is_some() && c.tx_pointer.is_some()\n}","typeGuard":"fn has_utxo_id(c: &ProtoCoinSigned) -> bool { c.utxo_id.is_some() }","tryCatchPattern":"let utxo = c.utxo_id.as_ref().ok_or_else(|| {\n    anyhow!(\"CoinSigned input (owner {}) missing utxo_id\", hex::encode(&c.owner))\n})?;","preventionTips":["Model required nested submessages as mandatory in producer-side builders","Validate coin inputs (utxo_id + tx_pointer present) before encoding to proto","Keep conversion pre-checks in one helper reused across coin variants"],"tags":["rust","fuel","protobuf","serialization","coin-input","utxo","conversion"],"backgroundTag":null,"analyzedSha":"b9d4d170da3a31c9ace5f963d633b326348e0d42","analyzedAt":"2026-08-16T08:56:42.692Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}