FuelLabs/sway · error · anyhow::Error

Failed to find path root: `path` dependency \"{}\" has no pa

Error message

Failed to find path root: `path` dependency \"{}\" has no parent

What it means

find_path_root walks incoming edges upward from a node whose pinned source is Path; the loop assumes every path-sourced node has a parent (something depends on it). If a path-pinned node has no incoming edges, the walk cannot find a filesystem root and this error fires - a path dependency exists as a graph root, which is structurally invalid.

Source

Thrown at forc-pkg/src/pkg.rs:1339

            "invalid `path_root` for path dependency package {:?}",
            &graph[path_dep].name
        )
    }
    Ok(())
}

/// Given any node in the graph, find the node that is the path root for that node.
fn find_path_root(graph: &Graph, mut node: NodeIx) -> Result<NodeIx> {
    loop {
        let pkg = &graph[node];
        match pkg.source {
            source::Pinned::Path(ref src) => {
                let parent = graph
                    .edges_directed(node, Direction::Incoming)
                    .next()
                    .map(|edge| edge.source())
                    .ok_or_else(|| {
                        anyhow!(
                            "Failed to find path root: `path` dependency \"{}\" has no parent",
                            src
                        )
                    })?;
                node = parent;
            }
            source::Pinned::Git(_)
            | source::Pinned::Ipfs(_)
            | source::Pinned::Member(_)
            | source::Pinned::Registry(_) => {
                return Ok(node);
            }
        }
    }
}

/// Given an empty or partially completed `graph`, complete the graph.
///

View on GitHub (pinned to 47e5e902fa)

Solutions

  1. Delete Forc.lock and rebuild so paths are re-derived from the manifests.
  2. Avoid editing Forc.lock by hand - change dependencies in Forc.toml and let forc regenerate.
  3. If it recurs from a clean state, report to FuelLabs/sway with the manifests and lock.

Example fix

# before
forc build   # Failed to find path root: `path` dependency "../lib" has no parent

# after
rm Forc.lock && forc build
Defensive patterns

Strategy: try-catch

Validate before calling

// every Path-pinned node must have at least one dependent (incoming edge)
for ix in graph.node_indices() {
    if let forc_pkg::source::Pinned::Path(_) = graph[ix].source {
        if graph.edges_directed(ix, petgraph::Direction::Incoming).next().is_none() {
            // invalid structure: regenerate Forc.lock before building
        }
    }
}

Try / catch

match build_plan_result {
    Ok(plan) => { /* ... */ }
    Err(e) if e.to_string().contains("Failed to find path root") => {
        let _ = std::fs::remove_file(&lock_path);
        // regenerate once; if it reproduces from a clean lock, report upstream
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: A lock/graph where a Path-pinned package is a root node - e.g. Forc.lock hand-edited to pin the project itself as Path, or graph pruning removed a parent edge while leaving the child; typically not producible from well-formed manifests.

Common situations: Manually edited Forc.lock; artifacts of stale locks after removing dependents; forc-pkg regressions.

Related errors


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