FuelLabs/sway · error

failed to write lock file: {}

Error message

failed to write lock file: {}

What it means

The new Forc.lock serialized fine but fs::write(lock_path, string) failed; {} is the io::Error. The lock could not be persisted to disk: permission denied on the directory, read-only filesystem/mount, disk full, or lock_path colliding with a directory.

Source

Thrown at forc-pkg/src/pkg.rs:753

                    "The lock file {} needs to be updated (Cause: {}) \
                    but --locked was passed to prevent this.",
                    lock_path.to_string_lossy(),
                    cause,
                );
            }
            println_action_green(
                "Creating",
                &format!("a new `Forc.lock` file. (Cause: {cause})"),
            );
            let member_names = manifests
                .values()
                .map(|manifest| manifest.project.name.to_string())
                .collect();
            crate::lock::print_diff(&member_names, &lock_diff);
            let string = toml::ser::to_string_pretty(&new_lock)
                .map_err(|e| anyhow!("failed to serialize lock file: {}", e))?;
            fs::write(lock_path, string)
                .map_err(|e| anyhow!("failed to write lock file: {}", e))?;
            debug!("   Created new lock file at {}", lock_path.display());
        }

        Ok(plan)
    }

    /// Produce an iterator yielding all contract dependencies of given node in the order of
    /// compilation.
    pub fn contract_dependencies(&self, node: NodeIx) -> impl Iterator<Item = NodeIx> + '_ {
        let graph = self.graph();
        let connected: HashSet<_> = Dfs::new(graph, node).iter(graph).collect();
        self.compilation_order()
            .iter()
            .cloned()
            .filter(move |&n| n != node)
            .filter(|&n| {
                graph
                    .edges_directed(n, Direction::Incoming)

View on GitHub (pinned to 47e5e902fa)

Solutions

  1. Check write permission on the project directory (chmod u+w / chown) and that Forc.lock is a file, not a directory.
  2. Free disk space or raise the quota if the io error is No space left on device.
  3. Mount the workspace read-write in CI/Docker, or pre-generate the lock in a writable step.

Example fix

# before: read-only mount in CI
# - run: forc build
#   volumeMounts: readOnly: true

# after: write the lock in a writable stage
- run: forc build
docker run -v $PWD:/src -w /src ghcr.io/fuellabs/forc:latest forc build
Defensive patterns

Strategy: validation

Validate before calling

fn dir_is_writable(dir: &std::path::Path) -> bool {
    let probe = dir.join(".forc_write_probe");
    std::fs::write(&probe, b"").is_ok() && std::fs::remove_file(&probe).is_ok()
}
// check the project dir before building so the lock can be persisted

Prevention

When it happens

Trigger: Building in a directory the process cannot write (root-owned, chmod 555); Docker/CI read-only volume; ENOSPC; a stray directory named Forc.lock.

Common situations: Running forc via sudo-created project dirs; CI sandbox with read-only source mounts; full disks or quotas on build agents.

Related errors


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