FuelLabs/sway · error · anyhow::Error

Configurables section offset not found

Error message

Configurables section offset not found

What it means

get_bytecode_id detects a configurables-bearing binary by checking that instructions 4 and 5 (CONFIGURABLES_OFFSET_INSTR_LO/HI) both decode to fuel_asm::InvalidOpcode — the sentinel half-words encoding the configurables section offset. If they are not both InvalidOpcode, the expected preamble marker is absent and the function errors. The repo's own regression test reproduces this with a .bin produced by an older compiler that did not embed the offset.

Source

Thrown at forc-util/src/bytecode.rs:111

            }

            // Continue hashing the remaining instructions up to the configurables section offset.
            instructions
                .take(
                    configurables_offset / fuel_asm::Instruction::SIZE
                        - CONFIGURABLES_OFFSET_PREAMBLE,
                ) // Minus 6 because we already hashed the first six
                .for_each(|(_, raw)| {
                    hasher.update(raw);
                });

            let hash_result = hasher.finalize();
            let bytecode_id = format!("{hash_result:x}");
            return Ok(bytecode_id);
        }
    }

    Err(anyhow!("Configurables section offset not found"))
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_get_bytecode_id_happy() {
        // These binary files were generated from `examples/configurable_constants` and `examples/counter`
        // using `forc build` and `forc build --release` respectively.
        let bytecode_id: String =
            get_bytecode_id("tests/fixtures/bytecode/debug-counter.bin").expect("bytecode id");
        assert_eq!(
            bytecode_id,
            "e65aa988cae1041b64dc2d85e496eed0e8a1d8105133bd313c17645a1859d53b".to_string()
        );

        let bytecode_id =

View on GitHub (pinned to 47e5e902fa)

Solutions

  1. Rebuild the bytecode with the current `forc build` so the preamble contains the offset sentinel, then recompute the ID
  2. Clear build caches (out/, CI artifact caches) so old-compiler binaries are regenerated
  3. If you must support legacy binaries, hash them with a tool version matching the one that produced them

Example fix

# before (bin built by old compiler)
forc contract-id --bytecode-file cached_old_counter.bin

# after
forc build && forc contract-id --bytecode-file out/debug/counter.bin
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check that the preamble carries the configurables-offset sentinel
// (instructions 4 and 5 must decode to InvalidOpcode), mirroring get_bytecode_id.
fn has_configurables_offset(path: &Path) -> bool {
    let mut it = match forc_util::bytecode::parse_bytecode_to_instructions(path) {
        Ok(it) => it,
        Err(_) => return false,
    };
    let instrs: Vec<_> = (&mut it).take(6).collect();
    instrs.len() == 6
        && matches!(instrs[4].0, Err(_))
        && matches!(instrs[5].0, Err(_))
}

Try / catch

match get_bytecode_id(&path) {
    Ok(id) => Ok(id),
    Err(e) if e.to_string() == "Configurables section offset not found" => {
        Err(anyhow::anyhow!("{} was built by an older compiler; rebuild with current forc", path.display()))
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Hashing bytecode compiled by an old sway/forc version that predates the configurables-offset preamble, or hand-modified/malformed bytecode where the sentinel was clobbered.

Common situations: Computing contract IDs for artifacts built before a forc upgrade, CI caches holding stale .bin files across toolchain bumps, or checking in binaries built by mismatched toolchain versions.

Related errors


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