FuelLabs/sway · error

found dep {} without node entry in graph

Error message

found dep {} without node entry in graph

What it means

Lock::to_graph works in two passes: first every [[package]] entry becomes a graph node keyed by '<name> <source>' (or just the name when unambiguous), then every dependency line is looked up in that key map. This error means a dependency line references a key that has no matching package entry - the lock's edges are inconsistent with its node list.

Source

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

                .as_ref()
                .into_iter()
                .flatten()
                .map(|contract_dep| (contract_dep, UnparsedDepKind::Contract));
            // If `pkg.dependencies` is None, we will be collecting an empty list of
            // lib_deps so that we will omit them during edge adding phase
            let lib_deps = pkg
                .dependencies
                .as_ref()
                .into_iter()
                .flatten()
                .map(|lib_dep| (lib_dep, UnparsedDepKind::Library));
            for (dep_line, dep_kind) in lib_deps.chain(contract_deps) {
                let (dep_name, dep_key, dep_salt) = parse_pkg_dep_line(dep_line)
                    .map_err(|e| anyhow!("failed to parse dependency \"{}\": {}", dep_line, e))?;
                let dep_node = pkg_to_node
                    .get(dep_key)
                    .copied()
                    .ok_or_else(|| anyhow!("found dep {} without node entry in graph", dep_key))?;
                let dep_name = dep_name.unwrap_or(&graph[dep_node].name).to_string();
                let dep_kind = match dep_kind {
                    UnparsedDepKind::Library => DepKind::Library,
                    UnparsedDepKind::Contract => {
                        let dep_salt = dep_salt.unwrap_or_default();
                        DepKind::Contract { salt: dep_salt }
                    }
                };
                let dep_edge = Edge::new(dep_name, dep_kind);
                graph.update_edge(node, dep_node, dep_edge);
            }
        }

        Ok(graph)
    }

    /// Create a diff between `self` and the `old` `Lock`.
    ///

View on GitHub (pinned to 47e5e902fa)

Solutions

  1. Delete Forc.lock and rebuild so the package table and dependency edges are regenerated together.
  2. When hand-fixing, ensure the dependency line's name and source exactly equal the target [[package]] entry's name and source.
  3. Treat Forc.lock as generated: resolve dependency conflicts in Forc.toml (or git ours/theirs on the lock) and regenerate.
Defensive patterns

Strategy: fallback

Validate before calling

// Rust, consistency pre-check: every dep-line key must exist among package keys.
// Build both sets as '<name> <source>' (or bare name when unambiguous) and diff them,
// surfacing missing entries before calling to_graph.

Try / catch

// Inconsistent lock -> regenerate rather than patch edges:
match lock.to_graph() {
    Ok(g) => { /* ... */ }
    Err(_) => { fs::remove_file(lock_path).ok(); /* rebuild plan from manifests */ }
}

Prevention

When it happens

Trigger: A Forc.lock where a package's dependency line (name plus source) does not exactly match any [[package]] entry - typically a merge kept the dependency line but dropped or altered the target package entry, or a hand edit changed one side (name or source) without updating the other.

Common situations: Git merges of Forc.lock resolving to an inconsistent mix of both sides; renames of dependencies; two packages sharing a name where disambiguation keys (name+source) diverge between the edge and node sections.

Related errors


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