FuelLabs/fuel-core · error · anyhow::Error

Missing code for contract: {id}

Error message

Missing code for contract: {id}

What it means

While converting snapshot tables into a chain/genesis StateConfig, the chain-config crate joins per-contract records: bytecode from a contract-code table, (utxo_id, tx_pointer) from ContractUtxoInfo::V1 entries, plus states and balances (crates/chain-config/src/config/state.rs:213-227). If a contract id appears in the UTXO set but has no entry in the contract-code map, building the config fails with 'Missing code for contract: {id}'. The snapshot's tables are inconsistent: the contract exists on-chain but its bytecode was not captured.

Source

Thrown at crates/chain-config/src/config/state.rs:224

            .collect();

        let mut contract_utxos: HashMap<_, _> = self
            .contract_utxo
            .into_iter()
            .map(|entry| match entry.value {
                ContractUtxoInfo::V1(utxo) => {
                    (entry.key, (utxo.utxo_id, utxo.tx_pointer))
                }
                _ => unreachable!(),
            })
            .collect();

        let contracts = contract_ids
            .into_iter()
            .map(|id| -> anyhow::Result<_> {
                let code = contract_code
                    .remove(&id)
                    .ok_or_else(|| anyhow::anyhow!("Missing code for contract: {id}"))?;
                let (utxo_id, tx_pointer) = contract_utxos
                    .remove(&id)
                    .ok_or_else(|| anyhow::anyhow!("Missing utxo for contract: {id}"))?;
                let states = state.remove(&id).unwrap_or_default();
                let balances = balance.remove(&id).unwrap_or_default();

                Ok(ContractConfig {
                    contract_id: id,
                    code,
                    tx_id: *utxo_id.tx_id(),
                    output_index: utxo_id.output_index(),
                    tx_pointer_block_height: tx_pointer.block_height(),
                    tx_pointer_tx_idx: tx_pointer.tx_index(),
                    states,
                    balances,
                })
            })
            .try_collect()?;

View on GitHub (pinned to b9d4d170da)

Solutions

  1. Regenerate the full snapshot from a synced node so the code and UTXO tables cover exactly the same contracts and block height.
  2. Before conversion, verify consistency: every contract id in the UTXO table must exist in the code table (see validation snippet).
  3. If the contract is intentionally absent, remove its UTXO, state, and balance rows from the snapshot tables as well.
  4. If a freshly generated snapshot still misses code, report upstream — the export path may have a gap for some contract types.

Example fix

// before — fails inside the config builder
let state_config = StateConfig::generate(&mut reader)?; // Missing code for contract: 0x…

// after — check table consistency before conversion
let missing: Vec<_> = contract_utxo_ids
    .iter()
    .filter(|id| !contract_code.contains_key(*id))
    .copied()
    .collect();
anyhow::ensure!(
    missing.is_empty(),
    "snapshot tables inconsistent, contracts without code: {missing:?}"
);
Defensive patterns

Strategy: validation

Validate before calling

// Verify snapshot table consistency before building the chain/genesis config
let missing_code: Vec<ContractId> = contract_utxo_ids
    .iter()
    .filter(|id| !contract_code.contains_key(*id))
    .copied()
    .collect();
anyhow::ensure!(
    missing_code.is_empty(),
    "snapshot tables inconsistent; contracts without code: {missing_code:?}"
);

Try / catch

match build_config(&reader) {
    Err(e) if e.to_string().contains("Missing code for contract") => {
        // snapshot tables are inconsistent → regenerate rather than patch
        regenerate_snapshot(&node_url).await?;
    }
    other => other?,
}

Prevention

When it happens

Trigger: Generating the StateConfig (snapshot-to-genesis conversion in chain-config) where contract_utxos contains a ContractId that the contract_code table lacks.

Common situations: Regenerating a genesis/snapshot with table ranges that don't line up; a partial or interrupted snapshot export that skipped code rows; manually pruning or editing parquet/JSON snapshot tables; mixing tables from two different snapshots or node versions.

Related errors


AI-assisted analysis of FuelLabs/fuel-core@b9d4d170da (2026-08-16). Data as JSON: /api/errors/b1b7d8e5a00d26e6. Report an issue: GitHub.