block/buzz · error · IngestError::Rejected
kind:9002 must include at least one metadata tag (name, abou
Error message
kind:9002 must include at least one metadata tag (name, about, archived, topic, purpose, visibility, ttl)
What it means
Thrown when a kind:9002 (EDIT_METADATA) event contains none of the recognized metadata tags: name, about, archived, topic, purpose, visibility, ttl. The relay requires at least one recognized tag before evaluating permissions or storing the edit. Unrecognized tags (including typos like "topics" or "names") do not count.
Source
Thrown at crates/buzz-relay/src/handlers/side_effects.rs:508
}
}
9002 => {
// EDIT_METADATA: require at least one recognized metadata tag.
const RECOGNIZED_TAGS: &[&str] = &[
"name",
"about",
"archived",
"topic",
"purpose",
"visibility",
"ttl",
];
let has_recognized = event
.tags
.iter()
.any(|t| RECOGNIZED_TAGS.contains(&t.kind().to_string().as_str()));
if !has_recognized {
return Err(anyhow::anyhow!(
"kind:9002 must include at least one metadata tag (name, about, archived, topic, purpose, visibility, ttl)"
));
}
// Validate archived values before storage.
for t in event.tags.iter() {
if t.kind().to_string() == "archived" {
match t.content() {
Some("true") | Some("false") => {}
Some(v) => {
return Err(anyhow::anyhow!(
"invalid archived value: {v} (must be \"true\" or \"false\")"
));
}
None => {
return Err(anyhow::anyhow!("archived tag must have a value"));
}
}View on GitHub (pinned to f956e6fe06)
Solutions
- Add at least one recognized tag: ["name", ...], ["about", ...], ["archived", ...], ["topic", ...], ["purpose", ...], ["visibility", ...], or ["ttl", ...].
- Check for tag typos — the matcher compares the tag kind string exactly (lowercase, singular).
- If you only meant to change topic/purpose, those count as recognized and additionally only require membership.
- Validate the tag set client-side before publishing (see defense).
Example fix
// before — no recognized metadata tag
{ kind: 9002, tags: [["h", ch], ["emoji", "🔥"]] }
// → "kind:9002 must include at least one metadata tag (...)"
// after — include a recognized tag
{ kind: 9002, tags: [["h", ch], ["topic", "Release coordination"]] } Defensive patterns
Strategy: validation
Validate before calling
const RECOGNIZED = ["name", "about", "archived", "topic", "purpose", "visibility", "ttl"] as const;
function buildMetadataEvent(channelId: string, fields: Record<string, string>) {
const tags: string[][] = [["h", channelId]];
for (const [k, v] of Object.entries(fields)) {
if ((RECOGNIZED as readonly string[]).includes(k)) tags.push([k, v]);
}
if (tags.length === 1) throw new Error("kind:9002 needs at least one of: " + RECOGNIZED.join(", "));
return { kind: 9002, tags };
} Type guard
function hasRecognizedMetadataTag(tags: string[][]): boolean {
const recognized = new Set(["name", "about", "archived", "topic", "purpose", "visibility", "ttl"]);
return tags.some((t) => recognized.has(t[0]));
} Try / catch
try {
await sdk.publish(editEvent);
} catch (e) {
if (String(e).includes("must include at least one metadata tag")) {
throw new Error(`No recognized field in edit — supported: name, about, archived, topic, purpose, visibility, ttl`);
} else throw e;
} Prevention
- Type the edit payload as a partial of the seven known fields so unknown keys fail at compile time.
- Keep tag kind strings lowercase and singular; reject anything else in your builder.
- Add a unit test asserting every editable field your UI exposes maps to a recognized tag kind.
When it happens
Trigger: Publishing kind:9002 with only unknown tags, e.g. [["h", ch], ["emoji", "🔥"], ["picture", url]], or with a misspelled tag kind such as ["desc", ...] instead of ["about", ...].
Common situations: Porting NIP-29 edit payloads from other relay implementations that accept extra tags; SDK versions that emit different tag names; hand-built events where a trailing 's' or camelCase tag slips in.
Related errors
- invalid archived value: {v} (must be "true" or "false")
- archived tag must have a value
- channel name is required
- invalid visibility value: {v} (must be "open" or "private")
- visibility tag must have a value
AI-assisted analysis of block/buzz@f956e6fe06 (2026-08-16).
Data as JSON: /api/errors/7f303c6927c92498.
Report an issue: GitHub.