block/buzz · error
sign kind:39002: {e}
Error message
sign kind:39002: {e} What it means
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.
Source
Thrown at crates/buzz-admin/src/main.rs:617
.tags(tags)
.sign_with_keys(&relay_keys)
.map_err(|e| anyhow::anyhow!("sign kind:39001: {e}"))?;
db.replace_addressable_event(tenant.community(), &event, Some(channel.id))
.await?;
}
}
// kind:39002 — members
{
let mut tags: Vec<Tag> = vec![Tag::parse(["d", &channel_id_str])?];
for m in &members {
let pk = hex::encode(&m.pubkey);
tags.push(Tag::parse(["p", &pk, "", &m.role])?);
}
let event = EventBuilder::new(Kind::Custom(39002), "")
.tags(tags)
.sign_with_keys(&relay_keys)
.map_err(|e| anyhow::anyhow!("sign kind:39002: {e}"))?;
db.replace_addressable_event(tenant.community(), &event, Some(channel.id))
.await?;
}
reconciled += 1;
}
println!(
"Reconciled {reconciled} channels ({skipped} already had events, {} total).",
channels.len()
);
Ok(())
}
View on GitHub (pinned to f956e6fe06)
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.
Defensive patterns
Strategy: validation
Validate before calling
# pre-verify the key once; member-tag content cannot cause this specific failure
python3 -c "import sys; bytes.fromhex(sys.argv[1])" "$BUZZ_RELAY_PRIVATE_KEY" \
|| { echo 'relay key is not valid hex' >&2; exit 1; } Try / catch
if stderr.contains("sign kind:39002") { retry once; persistent failure => check dependency pinning, then report with {e} and request id } Prevention
- 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).
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- sign kind:39000: {e}
- sign kind:39001: {e}
- invalid BUZZ_RELAY_PRIVATE_KEY: {e}
- BUZZ_RELAY_PRIVATE_KEY is required for add-member/remove-mem
- invalid relay key: {e}
AI-assisted analysis of block/buzz@f956e6fe06 (2026-08-16).
Data as JSON: /api/errors/d214c3f99903c3c9.
Report an issue: GitHub.