ruvnet/ruflo · error · Error

roomLabel may only contain [A-Za-z0-9_.\\-:/@#]

Error message

roomLabel may only contain [A-Za-z0-9_.\\-:/@#]

What it means

validateRoomLabel() enforces an allow-list charset: only A-Za-z0-9, underscore, dot, hyphen, colon, slash, at-sign, and '#' pass. The '#' is deliberately allowed because rooms are conventionally named '#sales', '#finance'. Any other character — space, comma, unicode/emoji, quotes — throws with the allow-list spelled out in the message.

Solutions

  1. Normalize labels before the call: lowercase, replace whitespace runs with '-', strip non-ASCII
  2. Use the conventional form '#kebab-case-name' with only allow-listed characters
  3. Validate at the UI/API boundary with the same regex /^[A-Za-z0-9_.\-:/@#]+$/ so users get an early, friendly error

Example fix

// before — space in label
await callMCPTool('agentbbs_create_room', { roomLabel: '#project alpha' });

// after — normalized
await callMCPTool('agentbbs_create_room', { roomLabel: '#project-alpha' });
Defensive patterns

Strategy: validation

Validate before calling

const ROOM_LABEL_RE = /^[A-Za-z0-9_.\-:/@#]+$/;

function normalizeRoomLabel(raw: string): string {
  const cleaned = raw.trim().replace(/\s+/g, '-').replace(/[^A-Za-z0-9_.\-:/@#]/g, '');
  if (!ROOM_LABEL_RE.test(cleaned)) throw new Error(`cannot normalize label: ${raw}`);
  return cleaned;
}

Type guard

const hasAllowedRoomLabelCharset = (v: string): boolean => /^[A-Za-z0-9_.\-:/@#]+$/.test(v);

Prevention

When it happens

Trigger: Labels containing spaces ('#project alpha'), commas from list-join bugs, emojis or non-ASCII characters from user input, shell-quote characters, or HTML entities pasted from web UIs.

Common situations: User-typed room names in chat UIs forwarded verbatim; i18n deployments where labels contain accented characters; labels built by joining tokens with spaces instead of hyphens.

Related errors


AI-assisted analysis of ruvnet/ruflo@9c61c86f06 (2026-08-18). Data as JSON: /api/errors/1ca499ef21b3163f. Report an issue: GitHub.

Appendix: source

Thrown at v3/@claude-flow/cli/src/mcp-tools/agentbbs-tools.ts:103

function degradedResult(reason: string): { success: true; degraded: true; reason: string } {
  return { success: true, degraded: true, reason };
}

function resolveBasePath(input?: string): string {
  const p = input && typeof input === 'string' && input.length > 0
    ? input
    : '.agentbbs';
  if (/\.\.[\\/]|\0/.test(p)) throw new Error('basePath contains disallowed characters');
  const abs = isAbsolute(p) ? p : resolve(getProjectCwd(), p);
  return abs;
}

function validateRoomLabel(label: string): string {
  if (!label || typeof label !== 'string') throw new Error('roomLabel is required');
  if (label.length > 128) throw new Error('roomLabel exceeds 128 chars');
  // Rooms are conventionally `#sales`, `#finance`, etc. — keep `#` in the allow-list.
  if (!/^[A-Za-z0-9_.\-:/@#]+$/.test(label)) {
    throw new Error('roomLabel may only contain [A-Za-z0-9_.\\-:/@#]');
  }
  return label;
}

function validateRoomId(roomId: string): string {
  if (!roomId || typeof roomId !== 'string') throw new Error('roomId is required');
  if (roomId.length > 128) throw new Error('roomId exceeds 128 chars');
  if (!/^[A-Za-z0-9_.\-:/@#]+$/.test(roomId)) {
    throw new Error('roomId may only contain [A-Za-z0-9_.\\-:/@#]');
  }
  return roomId;
}

function ensureDir(dir: string): void {
  if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
}

function roomIdFromLabel(label: string): string {

View on GitHub (pinned to 9c61c86f06)