FuelLabs/sway · error · anyhow::Error

failed to serialize lock file: {}

Error message

failed to serialize lock file: {}

What it means

After `forc update` recomputes the dependency graph and builds a new Lock from it, the final step serializes with toml::ser::to_string_pretty; failure is wrapped as "failed to serialize lock file: <error>". Serialization fails only if the Lock graph contains data not representable in TOML (e.g. invalid string keys/values such as control characters in names), which normally indicates malformed manifest input.

Source

Thrown at forc/src/ops/forc_update.rs:55

    let manifest = ManifestFile::from_dir(this_dir)?;
    let lock_path = lock_path(manifest.dir());
    let old_lock = Lock::from_path(&lock_path).ok().unwrap_or_default();
    let offline = false;
    let member_manifests = manifest.member_manifests()?;
    let ipfs_node = command.ipfs_node.unwrap_or_default();
    let new_plan = pkg::BuildPlan::from_manifests(&member_manifests, offline, &ipfs_node)?;
    let new_lock = Lock::from_graph(new_plan.graph());
    let diff = new_lock.diff(&old_lock);
    let member_names = member_manifests
        .values()
        .map(|manifest| manifest.project.name.clone())
        .collect();
    lock::print_diff(&member_names, &diff);

    // If we're not only `check`ing, write the updated lock file.
    if !check {
        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))?;
        info!("   Created new lock file at {}", lock_path.display());
    } else {
        info!(" `--check` enabled: `Forc.lock` was not changed");
    }

    Ok(())
}

View on GitHub (pinned to 47e5e902fa)

Solutions

  1. Back up and delete Forc.lock, then rerun `forc update` to regenerate it from scratch
  2. Inspect member and dependency Forc.toml files for malformed names/paths and fix them
  3. Update forc — serialization failures after dependency-handling refactors are usually fixed in patch releases

Example fix

# before
forc update   # failed to serialize lock file: ...

# after
mv Forc.lock Forc.lock.bak && forc update
Defensive patterns

Strategy: fallback

Validate before calling

// Before forc update: back up the lock so a serialization failure is recoverable,
// and sanity-check that member manifests parse.
std::fs::copy("Forc.lock", "Forc.lock.bak")?;
for m in member_manifest_paths() {
    PackageManifest::from_file(m)
        .map_err(|e| anyhow::anyhow!("malformed manifest {m}: {e}"))?;
}

Try / catch

match run_forc_update(dir) {
    Ok(()) => Ok(()),
    Err(e) if e.to_string().contains("failed to serialize lock file") => {
        // fallback: regenerate the lock from scratch, then retry once
        std::fs::remove_file(dir.join("Forc.lock")).ok();
        run_forc_update(dir)
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: `forc update` (without --check) on a workspace where some dependency name, path-derived key, or version string contains characters TOML cannot represent, or where a partial graph produced inconsistent state.

Common situations: Corrupted or hand-edited Forc.toml entries (odd package names/paths), dependencies whose repository-derived identifiers contain unusual characters, or forc bugs after major dependency-handling changes.

Related errors


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