FuelLabs/sway · error

missing pkg string

Error message

missing pkg string

What it means

Intended guard in parse_pkg_dep_line for a dependency line whose package-string part is empty - a line that carries a name (optionally parenthesized) but no '<name> <source>' payload after it. Like the sibling ')' check, split-based iteration makes this branch effectively unreachable; a genuinely empty package string instead surfaces downstream as the invalid-source parse error. Encountering it means a severely mangled dependency line.

Source

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

        false => (None, s),
        true => {
            // If we have the open bracket, grab everything until the closing bracket.
            let s = &s["(".len()..];
            let mut iter = s.split(')');
            let dep_name = iter
                .next()
                .ok_or_else(|| anyhow!("missing closing parenthesis"))?;
            // The rest is the unique package string and possibly the salt.
            let s = &s[dep_name.len() + ")".len()..];
            (Some(dep_name), s)
        }
    };

    // Check for salt.
    let mut iter = s.split('(');
    let pkg_str = iter
        .next()
        .ok_or_else(|| anyhow!("missing pkg string"))?
        .trim();
    let salt_str = iter.next().map(|s| s.trim()).map(|s| &s[..s.len() - 1]);
    let salt = match salt_str {
        Some(salt_str) => Some(
            fuel_tx::Salt::from_str(salt_str)
                .map_err(|e| anyhow!("invalid salt in lock file: {e}"))?,
        ),
        None => None,
    };

    Ok((dep_name, pkg_str, salt))
}

pub fn print_diff(member_names: &HashSet<String>, diff: &Diff) {
    print_removed_pkgs(member_names, diff.removed.iter().copied());
    print_added_pkgs(member_names, diff.added.iter().copied());
}

View on GitHub (pinned to 47e5e902fa)

Solutions

  1. Restore the full 'name source' (or '(name source) salt') line, or delete Forc.lock and regenerate it with forc build.
  2. Audit the file for truncation (check the last lines of each package block).
Defensive patterns

Strategy: fallback

Validate before calling

// Rust, reject dependency lines with an empty package-string part:
fn has_pkg_string(line: &str) -> bool {
    let s = line.trim().trim_start_matches('(').split(')').last().unwrap_or("");
    s.split('(').next().map(|p| !p.trim().is_empty()).unwrap_or(false)
}

Try / catch

// Practically unreachable branch; its trigger implies a mangled lock - regenerate:
match parse_pkg_dep_line(line) { Err(_) => { /* rm Forc.lock; forc build */ }, Ok(v) => v }

Prevention

When it happens

Trigger: A Forc.lock dependency line reduced to a bare name or '(name)' with everything after it missing.

Common situations: Truncated files; aggressive hand-editing; merge leftovers leaving only a fragment of a line.

Related errors


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