{"record":{"id":"926ea35bac3d0a1c","repo":"FuelLabs/sway","slug":"invalid-salt-in-lock-file-e","errorCode":null,"errorMessage":"invalid salt in lock file: {e}","messagePattern":"invalid salt in lock file: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"forc-pkg/src/lock.rs","lineNumber":332,"sourceCode":"                .next()\n                .ok_or_else(|| anyhow!(\"missing closing parenthesis\"))?;\n            // The rest is the unique package string and possibly the salt.\n            let s = &s[dep_name.len() + \")\".len()..];\n            (Some(dep_name), s)\n        }\n    };\n\n    // Check for salt.\n    let mut iter = s.split('(');\n    let pkg_str = iter\n        .next()\n        .ok_or_else(|| anyhow!(\"missing pkg string\"))?\n        .trim();\n    let salt_str = iter.next().map(|s| s.trim()).map(|s| &s[..s.len() - 1]);\n    let salt = match salt_str {\n        Some(salt_str) => Some(\n            fuel_tx::Salt::from_str(salt_str)\n                .map_err(|e| anyhow!(\"invalid salt in lock file: {e}\"))?,\n        ),\n        None => None,\n    };\n\n    Ok((dep_name, pkg_str, salt))\n}\n\npub fn print_diff(member_names: &HashSet<String>, diff: &Diff) {\n    print_removed_pkgs(member_names, diff.removed.iter().copied());\n    print_added_pkgs(member_names, diff.added.iter().copied());\n}\n\npub fn print_removed_pkgs<'a, I>(member_names: &HashSet<String>, removed: I)\nwhere\n    I: IntoIterator<Item = &'a PkgLock>,\n{\n    for pkg in removed {\n        if !member_names.contains(&pkg.name) {","sourceCodeStart":314,"sourceCodeEnd":350,"githubUrl":"https://github.com/FuelLabs/sway/blob/47e5e902faa42baf652dd6a0c88cd23390c1a614/forc-pkg/src/lock.rs#L314-L350","documentation":"In parse_pkg_dep_line, the parenthesized trailing component of a dependency line is parsed as a contract-dependency salt with fuel_tx::Salt::from_str, which requires exactly 64 hex characters (a 32-byte salt). Any non-hex or wrong-length body fails and is wrapped with this message. Note the parser blindly drops the last character of the token expecting ')', so even a technically-valid salt can fail if the closing paren layout is wrong; only contract-dependency lines carry salts.","triggerScenarios":"A contract-dependency entry in Forc.lock whose salt is not 64 hex chars - truncated during editing, 0x-prefixed when the parser does not expect a prefix, or with a missing ')' shifting the split.","commonSituations":"Hand-copied salts of the wrong length; prefixes from other tools; merge damage limited to the salt segment.","solutions":["Write the salt as exactly 64 hex characters inside the trailing parentheses, e.g. (auth git+...#c0ffee) 0000000000000000000000000000000000000000000000000000000000000000.","Delete Forc.lock and rebuild to regenerate contract-dependency lines from Forc.toml's [contract-dependencies] section.","If maintaining manually, verify length with: echo -n \"$SALT\" | wc -c (must be 64)."],"exampleFix":"# before (Forc.lock)\ncontract-dependencies = [ \"(auth git+https://github.com/x/auth#abc) 0xdeadbeef\" ]\n\n# after\ncontract-dependencies = [ \"(auth git+https://github.com/x/auth#abc) deadbeef00000000000000000000000000000000000000000000000000000000\" ]","handlingStrategy":"validation","validationCode":"// Rust, pre-check the salt body of a contract-dependency line:\nfn valid_salt_body(line: &str) -> Option<bool> {\n    let after = line.split('(').nth(1)?;\n    let body = after.strip_suffix(')').unwrap_or(after).trim();\n    Some(body.len() == 64 && body.chars().all(|c| c.is_ascii_hexdigit()))\n}","typeGuard":null,"tryCatchPattern":"// anyhow Result at lock load; map to a regeneration flow:\nmatch Lock::from_path(&p).and_then(|l| l.to_graph()) {\n    Err(e) if e.to_string().contains(\"invalid salt\") => { /* rm Forc.lock; rebuild */ }\n    other => other.unwrap(),\n}","preventionTips":["Author contract-dependency salts as exactly 64 hex chars (no 0x) in lock lines.","Declare salts in Forc.toml as HexSalt (0x + 64 hex) and let forc write the lock.","Lint salt length when generating lock files programmatically."],"tags":["forc","forc-pkg","lockfile","salt","parsing"],"backgroundTag":null,"analyzedSha":"47e5e902faa42baf652dd6a0c88cd23390c1a614","analyzedAt":"2026-08-16T07:57:45.555Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}