{"record":{"id":"4c5152873ca6dfe4","repo":"FuelLabs/fuel-core","slug":"coin-should-not-exist","errorCode":null,"errorMessage":"Coin should not exist","messagePattern":"Coin should not exist","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/fuel-core/src/service/genesis/importer/on_chain.rs","lineNumber":243,"sourceCode":"        asset_id: *coin.value.asset_id(),\n        tx_pointer: *coin.value.tx_pointer(),\n    }\n    .compress();\n\n    // ensure coin can't point to blocks in the future\n    let coin_height = coin.value.tx_pointer().block_height();\n    if coin_height > height {\n        return Err(anyhow!(\n            \"coin tx_pointer height ({coin_height}) cannot be greater than genesis block ({height})\"\n        ));\n    }\n\n    if transaction\n        .storage::<Coins>()\n        .replace(&utxo_id, &compressed_coin)?\n        .is_some()\n    {\n        return Err(anyhow!(\"Coin should not exist\"));\n    }\n\n    Ok(())\n}\n\nfn init_contract_latest_utxo(\n    transaction: &mut StorageTransaction<&mut GenesisDatabase>,\n    entry: &TableEntry<ContractsLatestUtxo>,\n    height: BlockHeight,\n) -> anyhow::Result<()> {\n    let contract_id = entry.key;\n\n    if entry.value.tx_pointer().block_height() > height {\n        return Err(anyhow!(\n            \"contract tx_pointer cannot be greater than genesis block\"\n        ));\n    }\n","sourceCodeStart":225,"sourceCodeEnd":261,"githubUrl":"https://github.com/FuelLabs/fuel-core/blob/b9d4d170da3a31c9ace5f963d633b326348e0d42/crates/fuel-core/src/service/genesis/importer/on_chain.rs#L225-L261","documentation":"Thrown by init_coin during on-chain genesis import (crates/fuel-core/src/service/genesis/importer/on_chain.rs). Each coin from the genesis state is written via StorageTransaction::replace(&utxo_id, &compressed_coin), and replace returns Some when the key already had a value. Seeing a previous value means this UTXO id was already inserted — either earlier in the same genesis batch or already present in the database — so the importer aborts to keep genesis collision-free and deterministic.","triggerScenarios":"The genesis state contains two coins with the same utxo_id (same tx id plus output index), or the node re-imports genesis into a database that already holds those coins because the db directory was left populated from a previous run with the same chain id.","commonSituations":"Hand-edited or machine-generated genesis JSON with duplicated coin entries; state snapshots regenerated with overlapping ranges; restarting a node against a dirty on-chain db directory; tests building a genesis::Config programmatically and pushing the same coin twice.","solutions":["Dedupe the genesis state: find coins sharing the same tx_id and output_index and remove the duplicates, then re-run the import.","If the database is dirty from an earlier run, wipe the configured db directory and start the node again so genesis imports into empty storage.","Verify the chain id in the node config matches the genesis you intend to run; a mismatch causes import over pre-existing state.","Regenerate the state snapshot with the official snapshot tooling and import the fresh output."],"exampleFix":"// before: genesis state lists the same coin twice (same tx_id + output_index)\n\"coins\": [\n  { \"owner\": \"0x...\", \"amount\": \"1000\", \"asset_id\": \"0x...\", \"tx_pointer\": { \"block_height\": 0, \"tx_index\": 0 }, \"output_index\": 0, \"tx_id\": \"0xaaaa...\" },\n  { \"owner\": \"0x...\", \"amount\": \"1000\", \"asset_id\": \"0x...\", \"tx_pointer\": { \"block_height\": 0, \"tx_index\": 0 }, \"output_index\": 0, \"tx_id\": \"0xaaaa...\" }\n]\n\n// after: the (tx_id, output_index) pair appears exactly once\n\"coins\": [\n  { \"owner\": \"0x...\", \"amount\": \"1000\", \"asset_id\": \"0x...\", \"tx_pointer\": { \"block_height\": 0, \"tx_index\": 0 }, \"output_index\": 0, \"tx_id\": \"0xaaaa...\" }\n]","handlingStrategy":"validation","validationCode":"use std::collections::HashSet;\n\nfn validate_genesis_coins(coins: &[fuel_core::chain_config::CoinConfig]) -> Result<(), String> {\n    let mut seen = HashSet::new();\n    for coin in coins {\n        if !seen.insert((coin.tx_id, coin.output_index)) {\n            return Err(format!(\n                \"duplicate coin utxo_id: tx {:?} output {}\",\n                coin.tx_id, coin.output_index\n            ));\n        }\n    }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"match genesis_importer.run().await {\n    Err(e) if e.to_string().contains(\"Coin should not exist\") => {\n        // report duplicate utxo_id in the genesis state; do not retry with the same input\n    }\n    rest => rest,\n}","preventionTips":["Generate genesis snapshots with official tooling instead of hand-editing JSON.","Run a uniqueness lint over all state tables (coins, messages, contracts, blobs) before import.","Start a fresh chain against an empty db directory; wipe leftovers between CI runs.","Pin one canonical genesis file per network and checksum it."],"tags":["genesis","storage","duplicate-data","fuel-core","rust"],"backgroundTag":null,"analyzedSha":"b9d4d170da3a31c9ace5f963d633b326348e0d42","analyzedAt":"2026-08-16T08:56:42.692Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}