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

  1. Always emit the explicit value: ["archived", "true"] or ["archived", "false"].
  2. Fix tag builders so the value slot is never conditionally omitted.
  3. 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

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


AI-assisted analysis of block/buzz@f956e6fe06 (2026-08-16). Data as JSON: /api/errors/9e1e33e48fb01ce9. Report an issue: GitHub.