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
- Normalize labels before the call: lowercase, replace whitespace runs with '-', strip non-ASCII
- Use the conventional form '#kebab-case-name' with only allow-listed characters
- 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
- Normalize user input (lowercase, hyphens for spaces, strip non-ASCII) before the call
- Adopt the '#kebab-case' convention for room names
- Run the same allow-list regex at your API boundary for friendly early errors
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
- roomId may only contain [A-Za-z0-9_.\\-:/@#]
- basePath contains disallowed characters
- msgType must be alnum + _ - and ≤64 chars
- roomId exceeds 128 chars
- roomId is required
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)