FuelLabs/sway · error · anyhow::Error

log id is missing

Error message

log id is missing

What it means

decode_fuel_vm_log_data builds a lookup from program_abi.logged_types keyed by each logged type's log_id string, then .get(&log_id) with this ok_or_else. The error means the receipt's log id has no corresponding logged_types entry in the ABI used for decoding — the ABI does not describe that log site.

Source

Thrown at forc-util/src/tx_utils.rs:97

        fuel_abi_types::abi::unified_program::UnifiedProgramABI::from_counterpart(program_abi)?;

    // Create type lookup (id, TypeDeclaration)
    let type_lookup = program_abi
        .types
        .iter()
        .map(|decl| (decl.type_id, decl.clone()))
        .collect::<HashMap<_, _>>();

    let logged_type_lookup: HashMap<_, _> = program_abi
        .logged_types
        .iter()
        .flatten()
        .map(|logged_type| (logged_type.log_id.as_str(), logged_type.application.clone()))
        .collect();

    let type_application = logged_type_lookup
        .get(&log_id)
        .ok_or_else(|| anyhow::anyhow!("log id is missing"))?;

    let abi_decoder = ABIDecoder::default();
    let param_type = ParamType::try_from_type_application(type_application, &type_lookup)?;
    let decoded_str = abi_decoder.decode_as_debug_str(&param_type, log_data)?;
    let decoded_log = DecodedLog { value: decoded_str };

    Ok(decoded_log)
}

/// Build [`RevertInfo`] from VM receipts and an optional program ABI.
/// This extracts the latest revert code from receipts (or a provided hint) and
/// decodes panic metadata (message/value/backtrace) using the ABI metadata if available.
pub fn revert_info_from_receipts(
    receipts: &[fuel_tx::Receipt],
    program_abi: Option<&fuel_abi_types::abi::program::ProgramABI>,
    revert_code_hint: Option<u64>,
) -> Option<RevertInfo> {
    let revert_code = receipts

View on GitHub (pinned to 47e5e902fa)

Solutions

  1. Rebuild the project and use the freshly generated ABI (out/debug/<pkg>-abi.json) that matches the bytecode that emitted the logs
  2. Ensure the ABI file you pass corresponds to the exact contract/script that produced the receipts
  3. Keep forc toolchain and fuel-abi-types versions consistent between build and decode steps

Example fix

# before
echo 'log("x")' >> src/main.sw; forc run --abi old_export-abi.json

# after
forc build && forc run --abi out/debug/my_pkg-abi.json
Defensive patterns

Strategy: validation

Validate before calling

// Verify the ABI describes this log id before decoding.
let known: std::collections::HashSet<&str> = program_abi
    .logged_types
    .iter()
    .flatten()
    .map(|lt| lt.log_id.as_str())
    .collect();
if !known.contains(log_id) {
    anyhow::bail!("ABI is stale: log id {log_id} not in logged_types — rebuild and use the fresh ABI");
}

Type guard

fn abi_covers_log_id(abi: &fuel_abi_types::abi::program::ProgramABI, id: &str) -> bool {
    abi.logged_types
        .iter()
        .flatten()
        .any(|lt| lt.log_id == id)
}

Try / catch

match decode_log_data(log_id, log_data, program_abi) {
    Ok(d) => Ok(d),
    Err(e) if e.to_string() == "log id is missing" => {
        eprintln!("skipping undeclared log {log_id}; raw: {}", hex::encode(log_data));
        continue;
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Decoding a LogData receipt with a stale or mismatched ABI: bytecode rebuilt after adding/removing log statements (shifting log ids) while decoding against the previous Forc.abi.json, or passing another package's ABI.

Common situations: forc run/test against a deployed contract using an old ABI file, workspaces where the wrong member's ABI is picked up, or mixing toolchain versions whose log-id assignment differs.

Related errors


AI-assisted analysis of FuelLabs/sway@47e5e902fa (2026-08-16). Data as JSON: /api/errors/16dc3f8f4850bb7c. Report an issue: GitHub.