FuelLabs/sway · error

failed to parse dependency "{}": {}

Error message

failed to parse dependency "{}": {}

What it means

During Lock::to_graph, each package's dependency lines ('<name> <source>' or '(<name> <source>) <salt>') are parsed by parse_pkg_dep_line. A syntax error inside one line produces this message quoting the exact offending line, so the line itself tells you what is wrong. It signals lock-file corruption, not a missing package or network issue.

Source

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

            // If `pkg.contract_dependencies` is None, we will be collecting an empty list of
            // contract_deps so that we will omit them during edge adding phase
            let contract_deps = pkg
                .contract_dependencies
                .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)

View on GitHub (pinned to 47e5e902fa)

Solutions

  1. Delete Forc.lock and run forc build to regenerate every dependency line from Forc.toml.
  2. If editing is required, match the exact grammar: (name source) salt for contract deps with salt, name source otherwise.
  3. Adopt a repo convention to regenerate the lock after dependency changes instead of merging it.

Example fix

# before (Forc.lock)
dependencies = [
  "auth lib git+https://github.com/x/auth#<<<<<<< HEAD", # merge garbage
]

# after - regenerate: rm Forc.lock && forc build
Defensive patterns

Strategy: fallback

Validate before calling

// Rust, pre-validate each dependency line before graph construction:
fn dep_lines_ok(lock: &Lock) -> bool {
    lock.package.iter().all(|p| p.dependencies.as_ref()
        .into_iter().flatten().all(|l| parse_pkg_dep_line(l).is_ok()))
}

Try / catch

// Parse failure of a derived artifact -> regenerate:
match lock.to_graph() {
    Ok(g) => { /* ... */ }
    Err(_) => { fs::remove_file(lock_path).ok(); /* re-resolve from Forc.toml */ }
}

Prevention

When it happens

Trigger: A dependency line under a package entry in Forc.lock that does not parse: missing source after the name, stray characters, half-deleted merge-conflict text, or a salt part that breaks the expected bracket layout before the salt itself is validated.

Common situations: Manual edits to Forc.lock; bad merge-conflict resolution; tools that reformat the lock file; mismatched forc versions writing subtly different line formats.

Understand the failure class

Related errors


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