FuelLabs/sway · error
graph contains no project node
Error message
graph contains no project node
What it means
find_proj_node scans the dependency graph for the unique node whose name equals proj_name and that has no incoming edges (nothing depends on it). Zero matches produce this error: the package being built is not present as a root in the graph. Typically the project name in Forc.toml no longer agrees with what the lock/graph contains, or every occurrence of the package is consumed as a dependency of another node.
Source
Thrown at forc-pkg/src/pkg.rs:893
}
/// Given a graph and the known project name retrieved from the manifest, produce an iterator
/// yielding any nodes from the graph that might potentially be a project node.
fn potential_proj_nodes<'a>(g: &'a Graph, proj_name: &'a str) -> impl 'a + Iterator<Item = NodeIx> {
member_nodes(g).filter(move |&n| g[n].name == proj_name)
}
/// Given a graph, find the project node.
///
/// This should be the only node that satisfies the following conditions:
///
/// - The package name matches `proj_name`
/// - The node has no incoming edges, i.e. is not a dependency of another node.
fn find_proj_node(graph: &Graph, proj_name: &str) -> Result<NodeIx> {
let mut potentials = potential_proj_nodes(graph, proj_name);
let proj_node = potentials
.next()
.ok_or_else(|| anyhow!("graph contains no project node"))?;
match potentials.next() {
None => Ok(proj_node),
Some(_) => Err(anyhow!("graph contains more than one project node")),
}
}
/// Checks if the toolchain version is in compliance with minimum implied by `manifest`.
///
/// If the `manifest` is a ManifestFile::Workspace, check all members of the workspace for version
/// validation. Otherwise only the given package is checked.
fn validate_version(member_manifests: &MemberManifestFiles) -> Result<()> {
for member_pkg_manifest in member_manifests.values() {
validate_pkg_version(member_pkg_manifest)?;
}
Ok(())
}
/// Check minimum forc version given in the package manifest fileView on GitHub (pinned to 47e5e902fa)
Solutions
- Delete Forc.lock and rebuild so the graph is regenerated from current manifests.
- Verify the package's [project] name is unique across the workspace and matches how dependents reference it.
- Run 'forc update' to resynchronize manifest and lock.
Example fix
# before forc build # graph contains no project node # after rm Forc.lock && forc build
Defensive patterns
Strategy: validation
Validate before calling
let names: std::collections::HashSet<String> =
member_manifests.values().map(|m| m.project.name.clone()).collect();
if !names.contains(&proj_name) {
// the build root is not among the loaded members: fix names or regenerate the lock
} Prevention
- After renaming a package, regenerate Forc.lock immediately.
- Keep the project name consistent between Forc.toml and how dependents reference it.
- Run 'forc check' after workspace restructures before full builds.
When it happens
Trigger: pkg_graph_to_manifest_map called with a pkg_name that matches no graph node; the member was renamed in [project] name while Forc.lock still reflects the old name; the project depends on a package with the same name so both nodes have incoming edges; stale lock after workspace restructuring.
Common situations: Renaming a package without regenerating Forc.lock; two workspace members sharing a name; partially applied workspace reorganizations.
Related errors
- graph contains more than one project node
- Couldn't find manifest file for {}
- Cannot find manifest for {}
- more than one root package detected in graph
- Cannot get parent dir of {:?}
AI-assisted analysis of FuelLabs/sway@47e5e902fa (2026-08-16).
Data as JSON: /api/errors/6da7c79ba4db01ea.
Report an issue: GitHub.