{"record":{"id":"39c680b1d16174bb","repo":"FuelLabs/sway","slug":"e","errorCode":null,"errorMessage":"{e}","messagePattern":"\\{e\\}","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"forc-pkg/src/manifest/mod.rs","lineNumber":271,"sourceCode":"#[serde(rename_all = \"kebab-case\")]\npub struct Network {\n    #[serde(default = \"default_url\")]\n    pub url: String,\n}\n\n#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]\npub struct HexSalt(pub fuel_tx::Salt);\n\nimpl FromStr for HexSalt {\n    type Err = anyhow::Error;\n\n    fn from_str(s: &str) -> Result<Self, Self::Err> {\n        // cut 0x from start.\n        let normalized = s\n            .strip_prefix(\"0x\")\n            .ok_or_else(|| anyhow::anyhow!(\"hex salt declaration needs to start with 0x\"))?;\n        let salt: fuel_tx::Salt =\n            fuel_tx::Salt::from_str(normalized).map_err(|e| anyhow::anyhow!(\"{e}\"))?;\n        let hex_salt = Self(salt);\n        Ok(hex_salt)\n    }\n}\n\nimpl Display for HexSalt {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        let salt = self.0;\n        write!(f, \"{salt}\")\n    }\n}\n\nfn default_hex_salt() -> HexSalt {\n    HexSalt(fuel_tx::Salt::default())\n}\n\n#[serde_as]\n#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/FuelLabs/sway/blob/47e5e902faa42baf652dd6a0c88cd23390c1a614/forc-pkg/src/manifest/mod.rs#L253-L289","documentation":"After stripping 0x, HexSalt::from_str delegates to fuel_tx::Salt::from_str, which demands exactly 64 hex characters (the 32-byte Salt type). This pass-through error fires for wrong-length or non-hex bodies - the message is the underlying fuel-tx error verbatim. It is the second of the two salt parse failures (the first being the missing-0x check one line above).","triggerScenarios":"A salt like 0xdeadbeef (too short), 0x plus more/fewer than 64 hex chars, or containing non-hex characters (g-z, punctuation) inside a contract-dependency salt field or CLI --salt value.","commonSituations":"Short placeholder salts (0x0); copying truncated salts; mixed-in checksum characters that are not hex; line-wrapping in editors splitting the salt string.","solutions":["Use exactly 64 hex characters after 0x (32 bytes).","For the zero salt write 0x followed by 64 zeros, or omit the salt to get the default.","Verify programmatically: the string after 0x must have len 64 and contain only [0-9a-fA-F]."],"exampleFix":"# before\nsalt = \"0x1234\"\n\n# after\nsalt = \"0x0000000000000000000000000000000000000000000000000000000000001234\"","handlingStrategy":"validation","validationCode":"// Rust, full salt-shape check before parsing:\nfn valid_salt(s: &str) -> bool {\n    match s.strip_prefix(\"0x\") {\n        Some(body) => body.len() == 64 && body.chars().all(|c| c.is_ascii_hexdigit()),\n        None => false,\n    }\n}","typeGuard":"// Type-guard style predicate usable as a gate:\nfn is_complete_hex_salt(s: &str) -> bool {\n    let b = s.as_bytes();\n    b.len() == 66 && b[0]==b'0' && b[1]==b'x'\n        && b[2..].iter().all(|c| c.is_ascii_hexdigit())\n}","tryCatchPattern":"// anyhow Result - surface the fuel-tx message (it names length/hex problems):\nmatch HexSalt::from_str(salt_str) {\n    Ok(s) => s,\n    Err(e) => { eprintln!(\"invalid salt body: {e}; need 64 hex chars after 0x\"); return; }\n}","preventionTips":["Salt bodies are exactly 32 bytes: 64 hex characters after 0x.","Generate salts programmatically (e.g. hex of a 32-byte hash) instead of hand-typing.","Avoid editor line-wrapping inside salt string literals."],"tags":["forc","manifest","salt","formatting"],"backgroundTag":null,"analyzedSha":"47e5e902faa42baf652dd6a0c88cd23390c1a614","analyzedAt":"2026-08-16T07:57:45.555Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}