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.

Solutions

  1. Delete Forc.lock and rebuild so the graph is regenerated from current manifests.
  2. Verify the package's [project] name is unique across the workspace and matches how dependents reference it.
  3. 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

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


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

Appendix: 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 file

View on GitHub (pinned to dad95cc42b)