FuelLabs/sway · error

invalid 'source' entry for package

Error message

invalid 'source' entry for package {} lock: {:?}

What it means

While converting a parsed Forc.lock back into a package graph (Lock::to_graph), every package entry's source string is parsed into a source::Pinned value (git+https://...#commit, path+..., registry+...). If the string matches no known pinned-source format, this error names the package and echoes the underlying parse error, pointing at that package entry in the lock.

Solutions

  1. Delete Forc.lock and run forc build to re-resolve and regenerate it from Forc.toml - the lock is a derived artifact, never worth hand-fixing.
  2. If the lock must be hand-maintained, correct the entry to a valid pinned form such as git+https://github.com/FuelLabs/sway?tag=v0.49.0#<40-hex-commit>.
  3. Pin one forc version across the team and CI so lock format stays consistent.

Example fix

# before (Forc.lock)
[[package]]
name = "std"
source = "github.com/FuelLabs/sway" # malformed

# after
[[package]]
name = "std"
source = "git+https://github.com/FuelLabs/sway?tag=v0.49.0#8b4f3dd2c6db4a1d1c0d3e0b1f0ad79d1cd4c6e4"
Defensive patterns

Strategy: fallback

Validate before calling

// Rust, validate source entries before Lock::to_graph by round-tripping:
// let pinned: Result<source::Pinned, _> = pkg.source.parse();
// surface the first failing package name instead of a graph-wide error.

Try / catch

// On this error, the lock is unrecoverable-by-parsing: fall back to regeneration.
match lock.to_graph() {
    Ok(g) => { /* ... */ }
    Err(e) => { let _ = fs::remove_file("Forc.lock"); /* re-run dependency fetch */ }
}

Prevention

When it happens

Trigger: A Forc.lock whose [[package]] source entries are malformed: hand-edited strings, leftover merge-conflict markers, or a lock written by a different forc version whose source grammar differs from the reader's.

Common situations: Hand-resolved git merges of Forc.lock; upgrading/downgrading forc while keeping the old lock; scripts that rewrite locks; team members on mismatched toolchain versions.

Related errors


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

Appendix: source

Thrown at forc-pkg/src/lock.rs:191

    /// Given a `Lock` loaded from a `Forc.lock` file, produce the graph of pinned dependencies.
    pub fn to_graph(&self) -> Result<pkg::Graph> {
        let mut graph = pkg::Graph::new();

        // Track the names which need to be disambiguated in the dependency list.
        let names = self.package.iter().map(|pkg| &pkg.name[..]);
        let disambiguate: HashSet<_> = names_requiring_disambiguation(names).collect();

        // Add all nodes to the graph.
        // Keep track of "<name> <source>" to node-index mappings for the edge collection pass.
        let mut pkg_to_node: HashMap<String, pkg::NodeIx> = HashMap::new();
        for pkg in &self.package {
            // Note: `key` may be either `<name> <source>` or just `<name>` if disambiguation not
            // required.
            let key = pkg.name_disambiguated(&disambiguate).into_owned();
            let name = pkg.name.clone();
            let source: source::Pinned = pkg.source.parse().map_err(|e| {
                anyhow!("invalid 'source' entry for package {} lock: {:?}", name, e)
            })?;
            let pkg = pkg::Pinned { name, source };
            let node = graph.add_node(pkg);
            pkg_to_node.insert(key, node);
        }

        // On the second pass, add all edges.
        for pkg in &self.package {
            let key = pkg.name_disambiguated(&disambiguate);
            let node = pkg_to_node[&key[..]];
            // If `pkg.contract_dependencies` is None, we will be collecting an empty list of
            // contract_deps so that we will omit them during edge adding phase
            let contract_deps = pkg
                .contract_dependencies
                .as_ref()
                .into_iter()
                .flatten()
                .map(|contract_dep| (contract_dep, UnparsedDepKind::Contract));

View on GitHub (pinned to 47e5e902fa)