{"record":{"id":"759135613f2881c9","repo":"FuelLabs/fuel-core","slug":"missing-tx-pointer-on-mint-transaction","errorCode":null,"errorMessage":"Missing tx_pointer on mint transaction","messagePattern":"Missing tx_pointer on mint transaction","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":672,"sourceCode":"                        e\n                    ))\n                })?;\n\n            let create_tx = FuelTransaction::create(\n                bytecode_witness_index,\n                policies,\n                salt,\n                storage_slots,\n                inputs,\n                outputs,\n                witnesses,\n            );\n\n            Ok(FuelTransaction::Create(create_tx))\n        }\n        ProtoTransactionVariant::Mint(proto_mint) => {\n            let tx_pointer_proto = proto_mint.tx_pointer.as_ref().ok_or_else(|| {\n                Error::Serialization(anyhow!(\"Missing tx_pointer on mint transaction\"))\n            })?;\n            let tx_pointer = tx_pointer_from_proto(tx_pointer_proto)?;\n            let input_contract_proto =\n                proto_mint.input_contract.as_ref().ok_or_else(|| {\n                    Error::Serialization(anyhow!(\n                        \"Missing input_contract on mint transaction\"\n                    ))\n                })?;\n            let input_contract = contract_input_from_proto(input_contract_proto)?;\n            let output_contract_proto =\n                proto_mint.output_contract.as_ref().ok_or_else(|| {\n                    Error::Serialization(anyhow!(\n                        \"Missing output_contract on mint transaction\"\n                    ))\n                })?;\n            let output_contract = contract_output_from_proto(output_contract_proto)?;\n            let mint_asset_id = fuel_core_types::fuel_types::AssetId::try_from(\n                proto_mint.mint_asset_id.as_slice(),","sourceCodeStart":654,"sourceCodeEnd":690,"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#L654-L690","documentation":"tx_from_proto_tx requires the tx_pointer sub-message on a Mint transaction; prost yields None when the field is absent and the code maps that to Error::Serialization. fuel-core's Mint transaction always carries a TxPointer, so the decode of the transaction and block fails.","triggerScenarios":"Decoding a proto block where a Mint transaction omitted its tx_pointer - an encoder that skips the field, schema drift between versions, or truncated data.","commonSituations":"Version skew between fuel-core releases; third-party or hand-built producers; fixtures that populate only some Mint fields.","solutions":["Debug-print the failing ProtoTransaction::Mint to confirm tx_pointer (and input_contract/output_contract) presence.","Fix the encoder to always set tx_pointer on mint transactions.","Pre-validate mint sub-messages before decoding and reject with position context.","Re-fetch the block from a compatible peer."],"exampleFix":"// before\nlet tx_pointer_proto = proto_mint.tx_pointer.as_ref().ok_or_else(|| {\n    Error::Serialization(anyhow!(\"Missing tx_pointer on mint transaction\"))\n})?;\n\n// after: pre-validate all mint sub-messages\nif proto_mint.tx_pointer.is_none()\n    || proto_mint.input_contract.is_none()\n    || proto_mint.output_contract.is_none()\n{\n    return Err(Error::Serialization(anyhow::anyhow!(\n        \"mint transaction missing tx_pointer/input_contract/output_contract\"\n    )));\n}","handlingStrategy":"type-guard","validationCode":"fn mint_tx_complete(mint: &ProtoMint) -> bool {\n    mint.tx_pointer.is_some()\n        && mint.input_contract.is_some()\n        && mint.output_contract.is_some()\n}","typeGuard":"fn mint_tx_decodable(mint: &ProtoMint) -> bool {\n    mint.tx_pointer.is_some()\n        && mint.input_contract.is_some()\n        && mint.output_contract.is_some()\n}","tryCatchPattern":"match tx_from_proto_tx(t) {\n    Ok(tx) => txs.push(tx),\n    Err(Error::Serialization(ctx)) if ctx.to_string().contains(\"mint transaction\") => {\n        tracing::warn!(?t, \"rejecting incomplete Mint transaction\");\n        return Err(Error::Serialization(ctx));\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Encoders must populate tx_pointer, input_contract and output_contract on every Mint transaction.","Pre-validate mint sub-messages before decoding blocks.","Watch fuel-core upgrades that change Mint transaction structure; re-run roundtrip tests."],"tags":["rust","fuel-core","protobuf","deserialization","mint-transaction","missing-field"],"backgroundTag":null,"analyzedSha":"b9d4d170da3a31c9ace5f963d633b326348e0d42","analyzedAt":"2026-08-16T08:56:42.692Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}