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 file

View on GitHub (pinned to 47e5e902fa)

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@47e5e902fa (2026-08-16). Data as JSON: /api/errors/6da7c79ba4db01ea. Report an issue: GitHub.