{"record":{"id":"a75e4627e8ae756b","repo":"block/buzz","slug":"sign-kind-39000-e","errorCode":null,"errorMessage":"sign kind:39000: {e}","messagePattern":"sign kind:39000: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/buzz-admin/src/main.rs","lineNumber":583,"sourceCode":"                    if !desc.is_empty() {\n                        tags.push(Tag::parse([\"about\", desc])?);\n                    }\n                }\n                if channel.visibility == \"private\" {\n                    tags.push(Tag::parse([\"private\"])?);\n                } else {\n                    tags.push(Tag::parse([\"public\"])?);\n                }\n                if channel.channel_type == \"dm\" {\n                    tags.push(Tag::parse([\"hidden\"])?);\n                }\n                tags.push(Tag::parse([\"closed\"])?);\n                tags.push(Tag::parse([\"t\", &channel.channel_type])?);\n\n                let event = EventBuilder::new(Kind::Custom(39000), \"\")\n                    .tags(tags)\n                    .sign_with_keys(&relay_keys)\n                    .map_err(|e| anyhow::anyhow!(\"sign kind:39000: {e}\"))?;\n                db.replace_addressable_event(tenant.community(), &event, Some(channel.id))\n                    .await?;\n            }\n\n            // kind:39001 — admins\n            {\n                let mut tags: Vec<Tag> = vec![Tag::parse([\"d\", &channel_id_str])?];\n                for m in members\n                    .iter()\n                    .filter(|m| m.role == \"owner\" || m.role == \"admin\")\n                {\n                    let pk = hex::encode(&m.pubkey);\n                    tags.push(Tag::parse([\"p\", &pk, &m.role])?);\n                }\n                let event = EventBuilder::new(Kind::Custom(KIND_NIP29_GROUP_ADMINS as u16), \"\")\n                    .tags(tags)\n                    .sign_with_keys(&relay_keys)\n                    .map_err(|e| anyhow::anyhow!(\"sign kind:39001: {e}\"))?;","sourceCodeStart":565,"sourceCodeEnd":601,"githubUrl":"https://github.com/block/buzz/blob/f956e6fe06a76e50cbd8fba1a162482e752e7f1a/crates/buzz-admin/src/main.rs#L565-L601","documentation":"While republishing a channel's kind:39000 (NIP-29 channel metadata) snapshot, EventBuilder::sign_with_keys(&relay_keys) returned an error, which reconcile_channels wraps with this message. Signing is a pure secp256k1 operation over the assembled tags, and since the keys already passed Keys::parse, a failure here is essentially an internal/unexpected condition (secp256k1 backend error) rather than an input problem — the Tag::parse calls that build the tags fail separately with their own messages. The underlying error is appended as {e}.","triggerScenarios":"A secp256k1 signing error surfacing from the nostr library — in practice this almost never fires: the key parsed cleanly and the event content is empty. If you see it, capture {e}; historically such errors indicate a corrupted key object or a nostr/secp256k1 version incompatibility after a dependency bump.","commonSituations":"After a workspace-wide `cargo update` that pulled an incompatible nostr/secp256k1 pairing; building with a patched/miscompiled crypto backend; otherwise not reproducible on re-run.","solutions":["Re-run the command once — if it succeeds, it was transient; if it persists it is deterministic and environmental.","Capture the {e} suffix and check for secp256k1/nostr version skew: `cargo tree -p buzz-admin -i secp256k1` and ensure nostr and secp256k1 versions are the ones the workspace pins (run `cargo update` rollback or use Cargo.lock as committed).","Re-validate the key independently (`Keys::parse` on the same value in a scratch binary or `nostr-tools key check` equivalent) to rule out a subtly corrupted value that still parses.","If reproducible with a pinned lockfile, report it with the full {e} text — this path should be unreachable for a parsed key."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"# keys are the only realistic input factor: pre-verify before reconcile\npython3 -c \"import sys; bytes.fromhex(sys.argv[1])\" \"$BUZZ_RELAY_PRIVATE_KEY\" \\\n  || { echo 'relay key is not valid hex' >&2; exit 1; }","typeGuard":null,"tryCatchPattern":"match cmd.status() { Err if stderr.contains(\"sign kind:39000\") => retry once, then capture stderr + `cargo tree -i secp256k1` for a bug report }","preventionTips":["Build with the committed Cargo.lock (--locked) so nostr/secp256k1 stay a validated pair.","Treat sign failures on parsed keys as environment/dependency bugs: capture {e} rather than changing channel data."],"tags":["buzz-admin","nostr","event-signing","secp256k1","internal-error"],"backgroundTag":"event-signing-failed","analyzedSha":"f956e6fe06a76e50cbd8fba1a162482e752e7f1a","analyzedAt":"2026-08-16T22:11:40.750Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}