{"record":{"id":"9e1e33e48fb01ce9","repo":"block/buzz","slug":"archived-tag-must-have-a-value","errorCode":null,"errorMessage":"archived tag must have a value","messagePattern":"archived tag must have a value","errorType":"validation","errorClass":"IngestError::Rejected","httpStatus":400,"severity":"error","filePath":"crates/buzz-relay/src/handlers/side_effects.rs","lineNumber":524,"sourceCode":"                .any(|t| RECOGNIZED_TAGS.contains(&t.kind().to_string().as_str()));\n            if !has_recognized {\n                return Err(anyhow::anyhow!(\n                    \"kind:9002 must include at least one metadata tag (name, about, archived, topic, purpose, visibility, ttl)\"\n                ));\n            }\n\n            // Validate archived values before storage.\n            for t in event.tags.iter() {\n                if t.kind().to_string() == \"archived\" {\n                    match t.content() {\n                        Some(\"true\") | Some(\"false\") => {}\n                        Some(v) => {\n                            return Err(anyhow::anyhow!(\n                                \"invalid archived value: {v} (must be \\\"true\\\" or \\\"false\\\")\"\n                            ));\n                        }\n                        None => {\n                            return Err(anyhow::anyhow!(\"archived tag must have a value\"));\n                        }\n                    }\n                }\n            }\n\n            // Validate channel names before storage. A name made entirely of\n            // display-prefix hashes becomes empty after canonicalization.\n            for t in event.tags.iter() {\n                if t.kind().to_string() == \"name\" {\n                    match t.content() {\n                        Some(v)\n                            if !buzz_core::channel::canonical_channel_name(v)\n                                .trim()\n                                .is_empty() => {}\n                        _ => {\n                            return Err(anyhow::anyhow!(\"channel name is required\"));\n                        }\n                    }","sourceCodeStart":506,"sourceCodeEnd":542,"githubUrl":"https://github.com/block/buzz/blob/f956e6fe06a76e50cbd8fba1a162482e752e7f1a/crates/buzz-relay/src/handlers/side_effects.rs#L506-L542","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n{ kind: 9002, tags: [[\"h\", ch], [\"archived\"]] }\n\n// after\n{ kind: 9002, tags: [[\"h\", ch], [\"archived\", \"true\"]] }","handlingStrategy":"validation","validationCode":"// Reject bare single-element tags before publish\nfunction assertNoBareTags(tags: string[][]) {\n  for (const t of tags) {\n    if (t.length < 2 || t[1] === undefined) {\n      throw new Error(`Tag \"${t[0]}\" is missing a value`);\n    }\n  }\n}","typeGuard":"function hasValue(t: string[]): boolean {\n  return t.length >= 2 && typeof t[1] === \"string\";\n}","tryCatchPattern":"try {\n  await sdk.publish(editEvent);\n} catch (e) {\n  if (String(e).includes(\"archived tag must have a value\")) {\n    throw new Error(\"Send [\\\"archived\\\", \\\"true\\\"|\\\"false\\\"] — bare flags are rejected\");\n  } else throw e;\n}","preventionTips":["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."],"tags":["nostr","validation","kind-9002","missing-tag-value","relay"],"backgroundTag":"missing-tag-value","analyzedSha":"f956e6fe06a76e50cbd8fba1a162482e752e7f1a","analyzedAt":"2026-08-16T22:11:40.750Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}