{"record":{"id":"f6e59a6df07ed380","repo":"ruvnet/ruflo","slug":"roomid-is-required","errorCode":null,"errorMessage":"roomId is required","messagePattern":"roomId is required","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/mcp-tools/agentbbs-tools.ts","lineNumber":80,"sourceCode":"    ? input\n    : '.agentbbs';\n  if (/\\.\\.[\\\\/]|\\0/.test(p)) throw new Error('basePath contains disallowed characters');\n  const abs = isAbsolute(p) ? p : resolve(getProjectCwd(), p);\n  return abs;\n}\n\nfunction validateRoomLabel(label: string): string {\n  if (!label || typeof label !== 'string') throw new Error('roomLabel is required');\n  if (label.length > 128) throw new Error('roomLabel exceeds 128 chars');\n  // Rooms are conventionally `#sales`, `#finance`, etc. — keep `#` in the allow-list.\n  if (!/^[A-Za-z0-9_.\\-:/@#]+$/.test(label)) {\n    throw new Error('roomLabel may only contain [A-Za-z0-9_.\\\\-:/@#]');\n  }\n  return label;\n}\n\nfunction validateRoomId(roomId: string): string {\n  if (!roomId || typeof roomId !== 'string') throw new Error('roomId is required');\n  if (roomId.length > 128) throw new Error('roomId exceeds 128 chars');\n  if (!/^[A-Za-z0-9_.\\-:/@#]+$/.test(roomId)) {\n    throw new Error('roomId may only contain [A-Za-z0-9_.\\\\-:/@#]');\n  }\n  return roomId;\n}\n\nfunction ensureDir(dir: string): void {\n  if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n}\n\nfunction roomIdFromLabel(label: string): string {\n  // Stable, deterministic roomId — strip leading `#`, lowercase, and append a\n  // short hash so we don't collide across two rooms with the same canonical\n  // label but different policies. Phase 1: deterministic over (label).\n  const norm = label.replace(/^#/, '').toLowerCase();\n  const h = createHash('sha256').update(`agentbbs:room:${norm}`).digest('hex').slice(0, 8);\n  return `${norm}-${h}`;","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/ruvnet/ruflo/blob/6b01dc5a687b26b3e218f796de45ec51f8fa9e8c/v3/@claude-flow/cli/src/mcp-tools/agentbbs-tools.ts#L62-L98","documentation":"Thrown by validateRoomId() when the supplied roomId is falsy, not a string, or empty. roomId is the canonical room identifier returned by federation_bbs_register and required by federation_bbs_publish / _watch. Unlike roomLabel it is the internal handle (deterministic hash), so it must be passed verbatim from the register result.","triggerScenarios":"Calling federation_bbs_publish without roomId; passing the roomLabel where roomId was expected; the register step failed or its result was not captured before publish.","commonSituations":"Two-step flow where the caller forgot to thread the register result into publish; a refactor that renamed the field; a fixture that hard-coded an empty roomId placeholder.","solutions":["Always capture the `roomId` from the federation_bbs_register result and pass it unchanged to publish/watch.","Validate the publish input has a non-empty roomId string at your boundary.","If you only have a label, call register first to obtain the roomId."],"exampleFix":"// before — forgot the register result\nfederation_bbs_publish({ msgType: 'alert', payload: {...} }); // throws\n// after\nconst reg = await callMCPTool('federation_bbs_register', { roomLabel: '#sales' });\nawait callMCPTool('federation_bbs_publish', { roomId: reg.roomId, msgType: 'alert', payload: {...} });","handlingStrategy":"validation","validationCode":"function requireRoomId(id: unknown): string {\n  if (typeof id !== 'string' || id.length === 0) {\n    throw new Error('roomId must be a non-empty string obtained from federation_bbs_register');\n  }\n  return id;\n}","typeGuard":"const isNonEmptyString = (v: unknown): v is string => typeof v === 'string' && v.length > 0;","tryCatchPattern":"null","preventionTips":["Always thread the register result's roomId into publish/watch — never hand-roll it.","Add an integration test that asserts publish uses the register-derived id.","Type the publish input so a missing roomId is a compile error."],"tags":["validation","agentbbs","federation","required-field"],"backgroundTag":null,"analyzedSha":"6b01dc5a687b26b3e218f796de45ec51f8fa9e8c","analyzedAt":"2026-08-12T13:20:50.148Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}