{"record":{"id":"d7ae3af7d5acba2d","repo":"ruvnet/ruflo","slug":"roomlabel-is-required","errorCode":null,"errorMessage":"roomLabel is required","messagePattern":"roomLabel is required","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/mcp-tools/agentbbs-tools.ts","lineNumber":99,"sourceCode":"  }\n  return _cliAvailable;\n}\n\nfunction degradedResult(reason: string): { success: true; degraded: true; reason: string } {\n  return { success: true, degraded: true, reason };\n}\n\nfunction resolveBasePath(input?: string): string {\n  const p = input && typeof input === 'string' && input.length > 0\n    ? 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 {","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/ruvnet/ruflo/blob/9c61c86f06b439af2a95085ae9bb0ca839662e41/v3/@claude-flow/cli/src/mcp-tools/agentbbs-tools.ts#L81-L117","documentation":"validateRoomLabel() requires a non-empty string as roomLabel for agentbbs room operations; an empty string, undefined, null, or non-string value throws before anything is created. roomLabel is the human-facing room name (conventionally '#sales', '#finance') from which the deterministic roomId is derived.","triggerScenarios":"Calling agentbbs room create/resolve tools with roomLabel omitted, set to '' after String coercion of undefined, or passed as a number/object; destructuring bugs that pass the wrong variable; LLM-composed calls that drop the field.","commonSituations":"Agent code forwarding optional UI input where the room name field was left blank; refactors renaming the parameter on one side but not the other; JSON payloads built with a typo'd key ('roomlabel').","solutions":["Pass a non-empty roomLabel string, e.g. '#ops' — include the conventional leading '#'","Check the exact key spelling ('roomLabel', camelCase) in the tool input","If the label is user-supplied, require it in your form/validation layer before calling the tool"],"exampleFix":"// before — label missing\nawait callMCPTool('agentbbs_create_room', { roomId: '#ops' });\n\n// after — correct parameter name\nawait callMCPTool('agentbbs_create_room', { roomLabel: '#ops' });","handlingStrategy":"validation","validationCode":"function requireRoomLabel(label: unknown): string {\n  if (typeof label !== 'string' || label.length === 0) {\n    throw new Error('roomLabel is required (e.g. \"#ops\")');\n  }\n  return label;\n}","typeGuard":"const isRoomLabel = (v: unknown): v is string => typeof v === 'string' && v.length > 0;","tryCatchPattern":null,"preventionTips":["Type the tool input (zod/typescript) so missing fields fail at your boundary","Require the room-name field in UI forms before dispatch","Use the exact camelCase key 'roomLabel'"],"tags":["validation","agentbbs","required-parameter","rooms"],"backgroundTag":"missing-required-argument","analyzedSha":"9c61c86f06b439af2a95085ae9bb0ca839662e41","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}