{"record":{"id":"d214c3f99903c3c9","repo":"block/buzz","slug":"sign-kind-39002-e","errorCode":null,"errorMessage":"sign kind:39002: {e}","messagePattern":"sign kind:39002: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/buzz-admin/src/main.rs","lineNumber":617,"sourceCode":"                    .tags(tags)\n                    .sign_with_keys(&relay_keys)\n                    .map_err(|e| anyhow::anyhow!(\"sign kind:39001: {e}\"))?;\n                db.replace_addressable_event(tenant.community(), &event, Some(channel.id))\n                    .await?;\n            }\n        }\n\n        // kind:39002 — members\n        {\n            let mut tags: Vec<Tag> = vec![Tag::parse([\"d\", &channel_id_str])?];\n            for m in &members {\n                let pk = hex::encode(&m.pubkey);\n                tags.push(Tag::parse([\"p\", &pk, \"\", &m.role])?);\n            }\n            let event = EventBuilder::new(Kind::Custom(39002), \"\")\n                .tags(tags)\n                .sign_with_keys(&relay_keys)\n                .map_err(|e| anyhow::anyhow!(\"sign kind:39002: {e}\"))?;\n            db.replace_addressable_event(tenant.community(), &event, Some(channel.id))\n                .await?;\n        }\n\n        reconciled += 1;\n    }\n\n    println!(\n        \"Reconciled {reconciled} channels ({skipped} already had events, {} total).\",\n        channels.len()\n    );\n    Ok(())\n}\n","sourceCodeStart":599,"sourceCodeEnd":631,"githubUrl":"https://github.com/block/buzz/blob/f956e6fe06a76e50cbd8fba1a162482e752e7f1a/crates/buzz-admin/src/main.rs#L599-L631","documentation":"While republishing a channel's kind:39002 (NIP-29 member list) snapshot — p-tags of `[pubkey, \"\", role]` for every member plus the d-tag — EventBuilder::sign_with_keys(&relay_keys) failed and reconcile_channels wrapped it. Identical failure class to the 39000/39001 sign wrappers: keys were validated by Keys::parse earlier, so this indicates an unexpected crypto-layer error ({e}) rather than malformed member data.","triggerScenarios":"reconcile-channels reaching the member-snapshot sign step and the secp256k1 backend returning an error; practically limited to dependency/toolchain anomalies (nostr/secp256k1 mismatch) since the inputs are pre-validated.","commonSituations":"Same as the other sign errors: version skew after dependency updates, patched crypto crates, exotic build targets. A channel with many members makes the signing payload larger but signing itself is O(1) over the serialized event, so size is not a realistic trigger.","solutions":["Re-run to check transience.","Compare nostr/secp256k1 versions against the committed lockfile and rebuild clean: `cargo tree -i secp256k1` / `cargo build --locked`.","Rule out the key by running any other signing subcommand (add-member) with the same BUZZ_RELAY_PRIVATE_KEY — if that also fails at signing, the environment/key is the common factor.","Collect {e} and the nostr version for a bug report if it persists on pinned deps."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"# pre-verify the key once; member-tag content cannot cause this specific failure\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":"if stderr.contains(\"sign kind:39002\") { retry once; persistent failure => check dependency pinning, then report with {e} and request id }","preventionTips":["Use `cargo build --locked` for production admin tooling.","Batch-reconcile during low traffic so a transient crypto-layer failure is cheap to retry idempotently (replace_addressable_event is idempotent per channel)."],"tags":["buzz-admin","nostr","event-signing","secp256k1","kind-39002"],"backgroundTag":"event-signing-failed","analyzedSha":"f956e6fe06a76e50cbd8fba1a162482e752e7f1a","analyzedAt":"2026-08-16T22:11:40.750Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}