{"record":{"id":"4ba3429210991535","repo":"FuelLabs/fuel-core","slug":"missing-input-variant","errorCode":null,"errorMessage":"Missing input variant","messagePattern":"Missing input variant","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":863,"sourceCode":"            })?;\n            let body = BlobBody {\n                id: blob_id,\n                witness_index,\n            };\n\n            let blob_tx =\n                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            )","sourceCodeStart":845,"sourceCodeEnd":881,"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#L845-L881","documentation":"ProtoInput models inputs as a oneof variant; when the variant field itself is None there is no way to tell coin/message/contract apart, so input_from_proto_input fails fast with this serialization error before any field checks.","triggerScenarios":"A transaction input proto with the variant oneof never set — an encoder produced a bare ProtoInput, or the payload was truncated after the outer message. Any transaction type containing inputs (script, upload, blob, upgrade, mint) can surface this.","commonSituations":"Default-constructed ProtoInput structs (prost makes all-oneof-None valid); partial serialization from a buggy client; schema-skew where the input oneof was renamed.","solutions":["Fix the producer to always populate the input variant oneof when appending inputs","Pre-scan inputs before conversion and reject transactions with variant-less ProtoInput entries, logging tx id and input position","Align proto definitions between producer and this crate","For legacy data, re-encode inputs with an explicit variant chosen from the transaction type context"],"exampleFix":"// before\nlet variant = proto_input.variant.as_ref().ok_or_else(|| Error::Serialization(anyhow!(\"Missing input variant\")))?;\n\n// after\nlet Some(variant) = proto_input.variant.as_ref() else {\n    // skip-and-report keeps one malformed input from killing the whole block ingest\n    report_bad_input(&proto_input);\n    continue;\n};","handlingStrategy":"type-guard","validationCode":"fn all_inputs_have_variants(tx: &ProtoTransaction) -> bool {\n    tx.inputs.iter().all(|i| i.variant.is_some())\n}","typeGuard":"fn input_variant_present(i: &ProtoInput) -> bool { i.variant.is_some() }","tryCatchPattern":"let variant = i.variant.as_ref().ok_or_else(|| {\n    anyhow!(\"input #{idx} in tx {:?} has no variant — producer bug\", tx_id)\n})?;","preventionTips":["Prohibit bare ProtoInput in producer code (wrap construction in a builder that requires a variant)","Scan whole transactions for variant-less inputs before starting conversion","Track which producer version emitted malformed inputs via telemetry"],"tags":["rust","fuel","protobuf","serialization","transaction-input","oneof","conversion"],"backgroundTag":null,"analyzedSha":"b9d4d170da3a31c9ace5f963d633b326348e0d42","analyzedAt":"2026-08-16T08:56:42.692Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}