ruvnet/ruflo · error · PodTemplateValidationError
pod-template at ${path}: roomId may only contain [A-Za-z0-9_
Error message
pod-template at ${path}: roomId may only contain [A-Za-z0-9_.\-:/@#] What it means
Thrown by validatePodTemplate() when the 'roomId' field contains characters outside the allowed set [A-Za-z0-9_.\-:/@#]. The roomId identifies the BBS room this pod serves. Unlike 'name', it permits a broader character set including uppercase, colons, slashes, and a few symbols, but still rejects spaces, quotes, and most punctuation.
Source
Thrown at v3/@claude-flow/cli/src/business-pods/pod-schema.ts:198
* `PodTemplateValidationError` with a JSON-pointer-style path on failure.
*
* Used by:
* - `business_pod_validate` MCP tool — returns the error verbatim
* - `pod-tick.mjs` — pre-flight check before any pod execution
* - any external schema-loader that wants typed templates
*/
export function validatePodTemplate(json: unknown): PodTemplate {
if (!isObject(json)) {
throw new PodTemplateValidationError('pod-template must be a JSON object', '/');
}
const name = requireString(json, 'name', '/');
if (!/^[a-z][a-z0-9-]*$/.test(name)) {
throw new PodTemplateValidationError('name must be lowercase-kebab (e.g. "sales")', '/');
}
const displayName = requireString(json, 'displayName', '/');
const roomId = requireString(json, 'roomId', '/');
if (!/^[A-Za-z0-9_.\-:/@#]+$/.test(roomId)) {
throw new PodTemplateValidationError(
'roomId may only contain [A-Za-z0-9_.\\-:/@#]',
'/',
);
}
const agents = requireArray(json, 'agents', '/', validatePodAgent);
if (agents.length === 0) {
throw new PodTemplateValidationError('agents must have ≥1 entry', '/');
}
const allowedMcpTools = requireArray(json, 'allowedMcpTools', '/', (t, tp) => {
if (typeof t !== 'string' || t.length === 0) {
throw new PodTemplateValidationError(
'allowedMcpTools entries must be non-empty strings',
tp,
);
}
return t;
});
if (allowedMcpTools.length === 0) {View on GitHub (pinned to 6b01dc5a68)
Solutions
- Strip spaces and disallowed punctuation from roomId
- Use only characters in [A-Za-z0-9_.\-:/@#] — colons and slashes are acceptable for namespace-style room IDs
- If the room needs a friendly name, put it in 'displayName' instead
Example fix
// before
{ "roomId": "sales room (west)" }
// after
{ "roomId": "sales:west" } Defensive patterns
Strategy: validation
Validate before calling
const ROOM_ID_RE = /^[A-Za-z0-9_.\-:/@#]+$/;
function isValidRoomId(id: string): boolean {
return ROOM_ID_RE.test(id);
}
if (!isValidRoomId(template.roomId)) {
console.error('roomId has invalid characters');
} Type guard
function isValidRoomId(id: string): boolean {
return /^[A-Za-z0-9_.\-:/@#]+$/.test(id);
} Try / catch
try {
validatePodTemplate(json);
} catch (e) {
if (e instanceof PodTemplateValidationError && e.message.includes('roomId')) {
// Sanitize or fix roomId characters
}
} Prevention
- Use only [A-Za-z0-9_.\-:/@#] characters in roomId
- Put human-readable descriptions in displayName, not roomId
- Avoid spaces, commas, and parentheses in roomId
When it happens
Trigger: The 'roomId' field contains a space, comma, parenthesis, brace, or any character not in [A-Za-z0-9_.\-:/@#]. For example 'sales room', 'sales(room)', or 'sales+pipeline'.
Common situations: A human-readable room description was placed in roomId instead of the machine identifier; the roomId was copied from a URL with query parameters like '?' or '='.
Related errors
- pod-template at ${path}: pod-template must be a JSON object
- pod-template at ${path}: field "${key}" must be a non-empty
- pod-template at ${path}: field "${key}" must be a finite num
- pod-template at ${path}: field "${key}" must be a boolean
- pod-template at ${path}: field "${key}" must be an array
AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12).
Data as JSON: /api/errors/ad42b4e4980dabe0.
Report an issue: GitHub.