{"record":{"id":"845f8b08c72e487c","repo":"block/buzz","slug":"invalid-archived-value-v-must-be-true-or-fa","errorCode":null,"errorMessage":"invalid archived value: {v} (must be \"true\" or \"false\")","messagePattern":"invalid archived value: (.+?) \\(must be \"true\" or \"false\"\\)","errorType":"validation","errorClass":"IngestError::Rejected","httpStatus":400,"severity":"error","filePath":"crates/buzz-relay/src/handlers/side_effects.rs","lineNumber":519,"sourceCode":"                \"ttl\",\n            ];\n            let has_recognized = event\n                .tags\n                .iter()\n                .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()","sourceCodeStart":501,"sourceCodeEnd":537,"githubUrl":"https://github.com/block/buzz/blob/f956e6fe06a76e50cbd8fba1a162482e752e7f1a/crates/buzz-relay/src/handlers/side_effects.rs#L501-L537","documentation":"Thrown when a kind:9002 event carries an \"archived\" tag whose value is neither the exact string \"true\" nor \"false\". Values are compared case-sensitively as strings before storage, so boolean JSON true, \"TRUE\", \"1\", or \"yes\" are all rejected.","triggerScenarios":"Publishing [[\"archived\", \"True\"], [\"archived\", \"1\"], or [\"archived\", true]] in a kind:9002 event. Note a JSON boolean true serializes to a missing/None content in some tag encoders and can instead surface as the 'must have a value' error.","commonSituations":"Clients mapping a UI toggle to a native boolean or an integer 0/1; language differences (Python 'True' capitalization leaking into payloads); copy-pasted payloads from APIs that use 0/1 flags.","solutions":["Send the lowercase string \"true\" or \"false\" as the tag value: [\"archived\", \"false\"].","If your data model stores booleans, convert explicitly at serialization: value ? \"true\" : \"false\".","Lint event payloads for archived tag values matching /^(true|false)$/ before publish."],"exampleFix":"// before\n{ kind: 9002, tags: [[\"h\", ch], [\"archived\", isArchived ? 1 : 0]] }\n\n// after\n{ kind: 9002, tags: [[\"h\", ch], [\"archived\", isArchived ? \"true\" : \"false\"]] }","handlingStrategy":"type-guard","validationCode":"// Normalize booleans to the exact relay enum before publish\nfunction archivedTag(value: boolean): string[] {\n  return [\"archived\", value ? \"true\" : \"false\"];\n}","typeGuard":"function isValidArchivedValue(v: string): boolean {\n  return v === \"true\" || v === \"false\";\n}\n\n// fail fast before publishing\nfor (const t of tags.filter((t) => t[0] === \"archived\")) {\n  if (!isValidArchivedValue(t[1] ?? \"\")) throw new Error(`archived must be \"true\" or \"false\", got ${t[1]}`);\n}","tryCatchPattern":"try {\n  await sdk.publish(editEvent);\n} catch (e) {\n  if (String(e).includes(\"invalid archived value\")) {\n    form.setError(\"archived\", \"Must be exactly true or false (lowercase)\");\n  } else throw e;\n}","preventionTips":["Never serialize native booleans or 0/1 into tag values — convert at the boundary.","Watch for locale-specific capitalization (Python str(True) → \"True\") in generated payloads.","Centralize tag-value encoders in one module instead of ad-hoc literals."],"tags":["nostr","validation","kind-9002","enum-value","relay"],"backgroundTag":"invalid-tag-value","analyzedSha":"f956e6fe06a76e50cbd8fba1a162482e752e7f1a","analyzedAt":"2026-08-16T22:11:40.750Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}