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(¶m_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 = receiptsView on GitHub (pinned to 47e5e902fa)
Solutions
- Rebuild the project and use the freshly generated ABI (out/debug/<pkg>-abi.json) that matches the bytecode that emitted the logs
- Ensure the ABI file you pass corresponds to the exact contract/script that produced the receipts
- 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
- Always regenerate and pass the ABI produced by the same `forc build` as the bytecode under test
- In scripts, `forc build` before any `forc run`/decode step instead of reusing checked-in ABI files
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
- only Fuel VM is supported for log decoding
- {}: file not found
- Incomplete bytecode
- Configurables section offset not found
- Serialized receipts does not contain {} th index
AI-assisted analysis of FuelLabs/sway@47e5e902fa (2026-08-16).
Data as JSON: /api/errors/16dc3f8f4850bb7c.
Report an issue: GitHub.