{"record":{"id":"af15a5a2828250da","repo":"FuelLabs/fuel-core","slug":"block-has-no-mint-transaction","errorCode":null,"errorMessage":"Block has no mint transaction","messagePattern":"Block has no mint transaction","errorType":"exception","errorClass":"GasPriceError::CouldNotFetchL2Block","httpStatus":null,"severity":"error","filePath":"crates/services/gas_price_service/src/common/fuel_core_storage_adapter.rs","lineNumber":198,"sourceCode":"    let used_gas = block_used_gas(fee, gas_price, gas_price_factor, block_gas_limit)?;\n    let info = BlockInfo::Block {\n        height: (*block.header().height()).into(),\n        gas_used: used_gas,\n        block_gas_capacity: block_gas_limit,\n        block_bytes: Postcard::encode(block).len() as u64,\n        block_fees: fee,\n        gas_price,\n    };\n    Ok(info)\n}\n\npub(crate) fn mint_values(block: &Block<Transaction>) -> GasPriceResult<(u64, u64)> {\n    let mint = block\n        .transactions()\n        .last()\n        .and_then(|tx| tx.as_mint())\n        .ok_or(GasPriceError::CouldNotFetchL2Block {\n            source_error: anyhow!(\"Block has no mint transaction\"),\n        })?;\n    Ok((*mint.mint_amount(), *mint.gas_price()))\n}\n\n// TODO: Don't take a direct dependency on `Postcard` as it's not guaranteed to be the encoding format\n// https://github.com/FuelLabs/fuel-core/issues/2443\npub(crate) fn block_bytes(block: &Block<Transaction>) -> u64 {\n    Postcard::encode(block).len() as u64\n}\n\nfn block_used_gas(\n    fee: u64,\n    gas_price: u64,\n    gas_price_factor: u64,\n    max_used_gas: u64,\n) -> GasPriceResult<u64> {\n    let scaled_fee =\n        fee.checked_mul(gas_price_factor)","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/FuelLabs/fuel-core/blob/b9d4d170da3a31c9ace5f963d633b326348e0d42/crates/services/gas_price_service/src/common/fuel_core_storage_adapter.rs#L180-L216","documentation":"mint_values expects the LAST transaction of a block to be a Mint transaction — the fee/gas-price mint the executor appends at the end of every produced block. When the final tx is not a mint (or the block has no transactions, e.g. genesis), get_block_info fails with GasPriceError::CouldNotFetchL2Block wrapping this message. The gas price service therefore cannot compute BlockInfo for such a block.","triggerScenarios":"Calling get_block_info(block) (gas price service initialization / block processing) on a block whose transactions() ends without a mint: the genesis block at height 0, blocks deserialized from an older fuel-core with a different mint placement/format, or hand-crafted test blocks built without appending a Mint.","commonSituations":"Gas price service starting at genesis height instead of height 1; replaying/importing blocks produced by older clients; custom test block builders that skip the mint transaction.","solutions":["Skip the genesis block (start gas price tracking at height >= 1) so every processed block has an executor-appended mint.","Ensure blocks are produced/imported by a fuel-core version whose executor appends the Mint transaction last (do not mix old-format blocks into a new chain).","When constructing blocks manually for tests, append a Mint transaction as the last transaction."],"exampleFix":"// before: feeding every block including genesis into the gas price service\nfor height in 0..=head { let info = get_block_info(&get_block(height)?, ...)?; }\n\n// after: skip the genesis block (no mint transaction)\nfor height in 1..=head { let info = get_block_info(&get_block(height)?, ...)?; }","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"use fuel_core_types::{blockchain::block::Block, fuel_tx::Transaction};\n\nfn block_has_trailing_mint(block: &Block<Transaction>) -> bool {\n    block.transactions().last().is_some_and(|tx| tx.as_mint().is_some())\n}\n\nif !block_has_trailing_mint(&block) {\n    // genesis or legacy-format block: skip gas price processing\n    continue;\n}","tryCatchPattern":"match get_block_info(&block, factor, gas_limit) {\n    Err(GasPriceError::CouldNotFetchL2Block { ref source_error })\n        if source_error.to_string().contains(\"no mint transaction\") =>\n    {\n        // expected for genesis/legacy blocks: skip this height, keep the service running\n    }\n    other => other,\n}","preventionTips":["Start gas price services at height 1; genesis never carries a mint transaction.","Do not import blocks produced by client versions with a different mint format into a new chain.","When building blocks manually in tests, always append the Mint transaction last."],"tags":["gas-price","mint-transaction","block-import","executor","rust"],"backgroundTag":null,"analyzedSha":"b9d4d170da3a31c9ace5f963d633b326348e0d42","analyzedAt":"2026-08-16T08:56:42.692Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}