block/buzz · error · IngestError::Rejected
archived tag must have a value
Error message
archived tag must have a value
What it means
Thrown when a kind:9002 event contains an "archived" tag with no value element at all (["archived"] — a bare tag). The relay refuses ambiguous bare tags: archiving state must be explicit because absent vs. present-but-empty have different meanings for this field.
Source
Thrown at crates/buzz-relay/src/handlers/side_effects.rs:524
.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"));
}
}
}
}
// Validate channel names before storage. A name made entirely of
// display-prefix hashes becomes empty after canonicalization.
for t in event.tags.iter() {
if t.kind().to_string() == "name" {
match t.content() {
Some(v)
if !buzz_core::channel::canonical_channel_name(v)
.trim()
.is_empty() => {}
_ => {
return Err(anyhow::anyhow!("channel name is required"));
}
}View on GitHub (pinned to f956e6fe06)
Solutions
- Always emit the explicit value: ["archived", "true"] or ["archived", "false"].
- Fix tag builders so the value slot is never conditionally omitted.
- If the intent was 'no change to archived', remove the archived tag entirely instead of leaving it bare.
Example fix
// before
{ kind: 9002, tags: [["h", ch], ["archived"]] }
// after
{ kind: 9002, tags: [["h", ch], ["archived", "true"]] } Defensive patterns
Strategy: validation
Validate before calling
// Reject bare single-element tags before publish
function assertNoBareTags(tags: string[][]) {
for (const t of tags) {
if (t.length < 2 || t[1] === undefined) {
throw new Error(`Tag "${t[0]}" is missing a value`);
}
}
} Type guard
function hasValue(t: string[]): boolean {
return t.length >= 2 && typeof t[1] === "string";
} Try / catch
try {
await sdk.publish(editEvent);
} catch (e) {
if (String(e).includes("archived tag must have a value")) {
throw new Error("Send [\"archived\", \"true\"|\"false\"] — bare flags are rejected");
} else throw e;
} Prevention
- Never conditionally omit the value slot when building tag pairs.
- Do not strip empty strings from tag arrays — the value position is structural.
- If a field should not change, drop the whole tag, not just its value.
When it happens
Trigger: Building tags as two-element pairs where the value slot is dropped, e.g. emitting [kind] instead of [kind, value]; SDK helpers that skip empty-string values; unzipping a tag array and losing the second element.
Common situations: Generic 'set flag' helpers that push [flagName] when the desired value is falsy; trimming code that filters out empty strings from tag arrays; JSON round-trips where null content collapses.
Related errors
- visibility tag must have a value
- ttl tag must have a value (seconds, or empty string to clear
- kind:9002 must include at least one metadata tag (name, abou
- invalid archived value: {v} (must be "true" or "false")
- channel name is required
AI-assisted analysis of block/buzz@f956e6fe06 (2026-08-16).
Data as JSON: /api/errors/9e1e33e48fb01ce9.
Report an issue: GitHub.