{"record":{"id":"2c710c8f233704e6","repo":"FuelLabs/sway","slug":"hex-salt-declaration-needs-to-start-with-0x","errorCode":null,"errorMessage":"hex salt declaration needs to start with 0x","messagePattern":"hex salt declaration needs to start with 0x","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"forc-pkg/src/manifest/mod.rs","lineNumber":269,"sourceCode":"\n#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]\n#[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","sourceCodeStart":251,"sourceCodeEnd":287,"githubUrl":"https://github.com/FuelLabs/sway/blob/47e5e902faa42baf652dd6a0c88cd23390c1a614/forc-pkg/src/manifest/mod.rs#L251-L287","documentation":"HexSalt::from_str requires salt strings to begin with the literal prefix 0x, which is stripped before delegating the remainder to fuel_tx::Salt::from_str. This specific error covers only the missing-prefix case; a present-but-malformed body produces the follow-on error instead. It surfaces wherever salts are parsed from text: contract-dependency salt fields in Forc.toml and the forc add --salt path.","triggerScenarios":"A salt value without 0x - e.g. salt = \"abcdef...\" under [contract-dependencies] in Forc.toml, or --salt 0000... on the command line - being parsed into a HexSalt.","commonSituations":"Copying a bare-hex salt from a block explorer or another tool; hand-writing manifest entries modeled on other hex fields; scripts generating salts without the prefix.","solutions":["Prefix the value with 0x: salt = \"0x<64 hex>\".","Copy salts from Forc.lock, which always prints them 0x-prefixed via the Display impl directly below this code.","When in doubt omit the salt and let the default zero salt apply."],"exampleFix":"# before (Forc.toml)\n[contract-dependencies]\nauth = { git = \"...\", salt = \"deadbeef0000...\" }\n\n# after\n[contract-dependencies]\nauth = { git = \"...\", salt = \"0xdeadbeef000000000000000000000000000000000000000000000000000000\" }","handlingStrategy":"validation","validationCode":"// Rust, enforce the 0x prefix before parsing a salt string:\nfn has_0x_prefix(s: &str) -> bool { s.trim().starts_with(\"0x\") }","typeGuard":null,"tryCatchPattern":"// anyhow Result from HexSalt::from_str; distinguish prefix vs body failure:\nmatch HexSalt::from_str(s) {\n    Err(e) if e.to_string().contains(\"needs to start with 0x\") =>\n        eprintln!(\"prefix the salt with 0x\"),\n    Err(e) => eprintln!(\"salt body invalid: {e}\"),\n    Ok(salt) => salt,\n}","preventionTips":["Author every salt in manifests/CLI as 0x + 64 hex chars.","Copy salts from generated Forc.lock files.","If you dislike prefixes, omit the salt and accept the default."],"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"}