{"record":{"id":"b620c2c4d4cc38df","repo":"block/buzz","slug":"invalid-buzz-relay-private-key-e-b620c2","errorCode":null,"errorMessage":"invalid BUZZ_RELAY_PRIVATE_KEY: {e}","messagePattern":"invalid BUZZ_RELAY_PRIVATE_KEY: (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"critical","filePath":"crates/buzz-relay/src/main.rs","lineNumber":427,"sourceCode":"        .read_database_url\n        .as_deref()\n        .unwrap_or(&config.database_url);\n    let search_pool = sqlx::postgres::PgPoolOptions::new()\n        .connect(search_db_url)\n        .await\n        .map_err(|e| anyhow::anyhow!(\"Search DB connection failed: {e}\"))?;\n    let search = SearchService::new(search_pool);\n    info!(\n        replica = config.read_database_url.is_some(),\n        \"Search service ready (Postgres FTS)\"\n    );\n\n    let workflow_config = buzz_workflow::WorkflowConfig::default();\n    let workflow_engine = Arc::new(WorkflowEngine::new(db.clone(), workflow_config));\n\n    let relay_keypair = if let Some(hex) = &config.relay_private_key {\n        nostr::Keys::parse(hex)\n            .map_err(|e| anyhow::anyhow!(\"invalid BUZZ_RELAY_PRIVATE_KEY: {e}\"))?\n    } else if !config.require_auth_token {\n        // Dev mode: use a deterministic keypair so addressable events (kind:39000/39001/39002)\n        // replace correctly across restarts. Without this, each restart generates a new pubkey\n        // and replace_addressable_event inserts duplicates instead of replacing.\n        const DEV_RELAY_PRIVKEY: &str =\n            \"0000000000000000000000000000000000000000000000000000000000000001\";\n        let keys = nostr::Keys::parse(DEV_RELAY_PRIVKEY).expect(\"hardcoded dev key is valid\");\n        tracing::warn!(\n            pubkey = %keys.public_key().to_hex(),\n            \"Using hardcoded dev relay keypair (BUZZ_REQUIRE_AUTH_TOKEN=false). \\\n             Set BUZZ_RELAY_PRIVATE_KEY for production.\"\n        );\n        keys\n    } else {\n        panic!(\n            \"BUZZ_RELAY_PRIVATE_KEY must be set when BUZZ_REQUIRE_AUTH_TOKEN=true. \\\n             A stable relay identity is required for production.\"\n        );","sourceCodeStart":409,"sourceCodeEnd":445,"githubUrl":"https://github.com/block/buzz/blob/f956e6fe06a76e50cbd8fba1a162482e752e7f1a/crates/buzz-relay/src/main.rs#L409-L445","documentation":"When BUZZ_RELAY_PRIVATE_KEY is set, nostr::Keys::parse validates it as a secp256k1 secret key. Non-hex characters, wrong length (not 64 hex chars / 32 bytes), a 0x prefix, or embedded whitespace/newlines all fail parsing and abort startup. Note this only fires when the key IS set — the missing-key case is handled by the separate NIP-43/require-auth-token checks.","triggerScenarios":"Setting the key to an nsec1... bech32 string, base64, a 0x-prefixed or 66-char value, or a secret-store value with a trailing newline or surrounding quotes.","commonSituations":"Copy-pasting nsec1... from Nostr clients; secret managers appending newlines; pasting the public key where the private key belongs.","solutions":["Set BUZZ_RELAY_PRIVATE_KEY to the raw 64-hex-character private key (the decoded nsec content, without the bech32 prefix)","Strip whitespace: `tr -d '[:space:]'` when injecting from files","Double-check you did not paste the pubkey"],"exampleFix":"# before\nBUZZ_RELAY_PRIVATE_KEY=nsec1qw508d6qejxtdg4y5r3zarvary0c5xw7k\n\n# after (hex body of the nsec, exactly 64 chars)\nBUZZ_RELAY_PRIVATE_KEY=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef","handlingStrategy":"validation","validationCode":"# The relay key must be exactly 64 hex characters.\n[[ \"${BUZZ_RELAY_PRIVATE_KEY:-}\" =~ ^[0-9a-fA-F]{64}$ ]] || { echo 'BUZZ_RELAY_PRIVATE_KEY must be 64 hex chars'; exit 1; }","typeGuard":"fn is_valid_secret_hex(s: &str) -> bool {\n    s.len() == 64 && s.bytes().all(|b| b.is_ascii_hexdigit())\n}","tryCatchPattern":null,"preventionTips":["Decode nsec1... values to raw hex before putting them in env","Trim whitespace/newlines when injecting secrets from files","Never confuse the pubkey with the private key in env naming"],"tags":["config","signing","nostr","env-vars","startup"],"backgroundTag":"invalid-private-key","analyzedSha":"f956e6fe06a76e50cbd8fba1a162482e752e7f1a","analyzedAt":"2026-08-16T22:11:40.750Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}