FuelLabs/sway · error · anyhow::Error

only Fuel VM is supported for log decoding

Error message

only Fuel VM is supported for log decoding

What it means

decode_log_data dispatches on the ProgramABI enum and only implements the Fuel variant (ProgramABI::Fuel -> decode_fuel_vm_log_data). Any other variant (e.g. an EVM ABI) returns this error, because the ABIDecoder/type-application machinery only understands Fuel VM log layouts.

Source

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

        Ok(serde_json::to_string_pretty(&receipt_to_json_array)?)
    } else {
        Ok(serde_json::to_string(&receipt_to_json_array)?)
    }
}

/// A `LogData` decoded into a human readable format with its type information.
pub struct DecodedLog {
    pub value: String,
}

pub fn decode_log_data(
    log_id: &str,
    log_data: &[u8],
    program_abi: &ProgramABI,
) -> anyhow::Result<DecodedLog> {
    match program_abi {
        ProgramABI::Fuel(program_abi) => decode_fuel_vm_log_data(log_id, log_data, program_abi),
        _ => Err(anyhow::anyhow!(
            "only Fuel VM is supported for log decoding"
        )),
    }
}

pub fn decode_fuel_vm_log_data(
    log_id: &str,
    log_data: &[u8],
    program_abi: &fuel_abi_types::abi::program::ProgramABI,
) -> anyhow::Result<DecodedLog> {
    let program_abi =
        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()))

View on GitHub (pinned to 47e5e902fa)

Solutions

  1. Build/run the project for the Fuel VM target so the Fuel JSON ABI is generated
  2. Pass the Fuel program ABI (from Forc.abi.json) to the decoding call
  3. If you wrap this API, early-match on ProgramABI::Fuel and give a clearer message for other targets

Example fix

// before
let decoded = decode_log_data(log_id, &data, &evm_abi)?;

// after
let ProgramABI::Fuel(fuel_abi) = &fuel_abi else {
    bail!("log decoding requires a Fuel program ABI");
};
let decoded = decode_log_data(log_id, &data, &ProgramABI::Fuel(fuel_abi.clone()))?;
Defensive patterns

Strategy: type-guard

Validate before calling

if !matches!(program_abi, ProgramABI::Fuel(_)) {
    anyhow::bail!("log decoding requires a Fuel VM program ABI");
}
let decoded = decode_log_data(log_id, log_data, program_abi)?;

Type guard

fn is_fuel_abi(abi: &ProgramABI) -> bool {
    matches!(abi, ProgramABI::Fuel(_))
}

Try / catch

let decoded = match decode_log_data(log_id, log_data, program_abi) {
    Ok(d) => d,
    Err(e) if e.to_string().contains("only Fuel VM") => {
        anyhow::bail!("non-Fuel target: raw log data is {}", hex::encode(log_data))
    }
    Err(e) => return Err(e),
};

Prevention

When it happens

Trigger: Calling forc_util::tx_utils::decode_log_data with a ProgramABI whose discriminant is not Fuel — concretely when a non-Fuel program ABI is passed to decode a LogData receipt during forc run/test log printing.

Common situations: Experimental/multi-VM toolchains that emit EVM-flavored ABIs, or tooling that constructs ProgramABI from the wrong JSON schema and lands in the non-Fuel arm.

Related errors


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