{"record":{"id":"153391fcb1676afc","repo":"FuelLabs/fuel-core","slug":"invalid-secret-key","errorCode":null,"errorMessage":"invalid secret key","messagePattern":"invalid secret key","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/keygen/src/lib.rs","lineNumber":123,"sourceCode":"            let p2p_keypair = secp256k1::Keypair::from(p2p_secret);\n            let libp2p_keypair = Keypair::from(p2p_keypair);\n            let peer_id = PeerId::from_public_key(&libp2p_keypair.public());\n            NewKeyResponse {\n                secret,\n                address: None,\n                peer_id: Some(peer_id),\n                typ: key_type,\n            }\n        }\n    })\n}\n\npub fn parse_secret(\n    key_type: KeyType,\n    secret: &str,\n) -> anyhow::Result<ParseSecretResponse> {\n    let secret =\n        SecretKey::from_str(secret).map_err(|_| anyhow::anyhow!(\"invalid secret key\"))?;\n    Ok(match key_type {\n        KeyType::BlockProduction => {\n            let address = Input::owner(&secret.public_key());\n            ParseSecretResponse {\n                address: Some(address),\n                peer_id: None,\n                typ: key_type,\n            }\n        }\n        KeyType::Peering => {\n            let mut bytes = *secret.deref();\n            let p2p_secret = secp256k1::SecretKey::try_from_bytes(&mut bytes)\n                .expect(\"Should be a valid private key\");\n            let p2p_keypair = secp256k1::Keypair::from(p2p_secret);\n            let libp2p_keypair = Keypair::from(p2p_keypair);\n            let peer_id = PeerId::from_public_key(&libp2p_keypair.public());\n            ParseSecretResponse {\n                address: None,","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/FuelLabs/fuel-core/blob/b9d4d170da3a31c9ace5f963d633b326348e0d42/crates/keygen/src/lib.rs#L105-L141","documentation":"keygen::parse_secret parses the input with fuel_crypto's SecretKey::from_str (a secp256k1 scalar). Any malformed input — wrong length, non-hex characters, a 0x prefix, surrounding whitespace, or a zero/out-of-range scalar — collapses into this single 'invalid secret key' message, so the underlying parse cause is not surfaced.","triggerScenarios":"Calling keygen parse (or any consumer of parse_secret) with a secret that is not exactly 64 hex characters encoding a valid non-zero secp256k1 scalar.","commonSituations":"Copying a key with a 0x prefix or surrounding quotes and whitespace from docs or env vars; truncated keys; pasting an ed25519 or libp2p key where a secp256k1 secret is expected; newline artifacts from files or CI secrets.","solutions":["Normalize the input: exactly 64 hex characters, no 0x prefix, no whitespace or trailing newline (trim first).","Validate the format before calling parse_secret: length 64 plus hex digits only.","If the key may be wrong, generate a fresh one with keygen generate (SecretKey::random) and use its hex output verbatim.","For KeyType::Peering, pass the secp256k1 secret from the libp2p keypair, not a public key or peer id."],"exampleFix":"// before\nlet resp = parse_secret(KeyType::BlockProduction, \"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef\")?;\n\n// after: strip prefix/whitespace, 64 hex chars only\nlet raw = \"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef\";\nlet resp = parse_secret(KeyType::BlockProduction, raw.trim().trim_start_matches(\"0x\"))?;","handlingStrategy":"validation","validationCode":"fn is_valid_secret_hex(s: &str) -> bool {\n    s.len() == 64 && s.bytes().all(|b| b.is_ascii_hexdigit())\n}\n\n// normalize before calling keygen::parse_secret\nlet secret = secret.trim().trim_start_matches(\"0x\");\nassert!(\n    is_valid_secret_hex(secret),\n    \"secret must be exactly 64 hex characters (32-byte secp256k1 scalar)\"\n);","typeGuard":"fn is_valid_secret_hex(s: &str) -> bool {\n    s.len() == 64 && s.bytes().all(|b| b.is_ascii_hexdigit())\n}","tryCatchPattern":"match keygen::parse_secret(key_type, &secret) {\n    Err(e) if e.to_string() == \"invalid secret key\" => {\n        // re-check format: length 64, hex only, no 0x prefix or whitespace; regenerate if malformed\n    }\n    rest => rest,\n}","preventionTips":["Store secrets as bare 64-char hex; trim whitespace and strip 0x before parsing.","Validate secret format in config loaders at startup, not at first use.","Do not mix key formats: secp256k1 secrets only for both KeyType variants."],"tags":["keygen","crypto","secp256k1","validation","fuel-core","rust"],"backgroundTag":null,"analyzedSha":"b9d4d170da3a31c9ace5f963d633b326348e0d42","analyzedAt":"2026-08-16T08:56:42.692Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}