FuelLabs/sway · error · anyhow::Error
{}: file not found
Error message
{}: file not found What it means
parse_bytecode_to_instructions in forc-util fails to File::open the given bytecode file and maps every open error to "<path>: file not found". The underlying io::Error is discarded (map_err(|_| ...)), so permission denied and true missing-file are indistinguishable. This parser feeds get_bytecode_id, used by forc contract-id / forc predicate-root bytecode hashing.
Source
Thrown at forc-util/src/bytecode.rs:54
fn next(&mut self) -> Option<InstructionWithBytes> {
let mut buffer = [0; fuel_asm::Instruction::SIZE];
// Read the next instruction into the buffer
match self.buf_reader.read_exact(&mut buffer) {
Ok(_) => fuel_asm::from_bytes(buffer)
.next()
.map(|inst| (inst, buffer.to_vec())),
Err(_) => None,
}
}
}
/// Parses a bytecode file into an iterator of instructions and their corresponding bytes.
pub fn parse_bytecode_to_instructions<P>(path: P) -> anyhow::Result<InstructionWithBytesIterator>
where
P: AsRef<Path> + Clone,
{
let f = File::open(path.clone())
.map_err(|_| anyhow!("{}: file not found", path.as_ref().to_string_lossy()))?;
let buf_reader = BufReader::new(f);
Ok(InstructionWithBytesIterator::new(buf_reader))
}
/// Gets the bytecode ID from a bytecode file. The bytecode ID is the hash of the bytecode after removing the
/// condigurables section, if any.
pub fn get_bytecode_id<P>(path: P) -> anyhow::Result<String>
where
P: AsRef<Path> + Clone,
{
let mut instructions = parse_bytecode_to_instructions(path.clone())?;
// Collect the first six instructions into a temporary vector
let mut first_six_instructions = Vec::with_capacity(CONFIGURABLES_OFFSET_PREAMBLE);
for _ in 0..CONFIGURABLES_OFFSET_PREAMBLE {
if let Some(instruction) = instructions.next() {
first_six_instructions.push(instruction);View on GitHub (pinned to 47e5e902fa)
Solutions
- Rebuild the project (`forc build`) and point at the freshly generated .bin under out/debug|release
- Verify the path from the directory you actually invoke forc from, or use an absolute path
- Check file permissions if the file visibly exists (the message cannot distinguish a permission failure)
Example fix
# before forc contract-id --bytecode-file out/debug/counter.bin # renamed package # after forc build && forc contract-id --bytecode-file out/debug/my_renamed_pkg.bin
Defensive patterns
Strategy: validation
Validate before calling
let path = std::path::Path::new(bytecode_path);
if !path.is_file() {
anyhow::bail!("bytecode file '{}' not found or unreadable", path.display());
}
let id = forc_util::bytecode::get_bytecode_id(path)?; Type guard
fn readable_bin(p: &std::path::Path) -> bool {
std::fs::metadata(p).map(|m| m.is_file()).unwrap_or(false)
} Try / catch
match forc_util::bytecode::get_bytecode_id(&path) {
Ok(id) => Ok(id),
Err(e) if e.to_string().ends_with("file not found") => {
Err(anyhow::anyhow!("build the project first: forc build (looked in {})", path.display()))
}
Err(e) => Err(e),
} Prevention
- Derive the .bin path from the package name (out/debug/<pkg>.bin) instead of hardcoding it in scripts
- Run `forc build` as a prerequisite step before any contract-id/predicate-root command
When it happens
Trigger: Calling get_bytecode_id / parse_bytecode_to_instructions with a wrong, moved, or unreadable path — e.g. `forc contract-id --bytecode-file out/debug/old-name.bin` after the project was renamed, or running from a directory where the relative output path does not resolve.
Common situations: Stale hardcoded paths in scripts after `forc build` output names change (binary named after the package), wrong cwd when invoking forc commands with relative paths, or file permissions blocking read access.
Related errors
- Incomplete bytecode
- Configurables section offset not found
- Serialized receipts does not contain {} th index
- only Fuel VM is supported for log decoding
- log id is missing
AI-assisted analysis of FuelLabs/sway@47e5e902fa (2026-08-16).
Data as JSON: /api/errors/823ce4d047b89f23.
Report an issue: GitHub.