ruvnet/ruflo · error · PodTemplateValidationError

pod-template at ${path}: name must be lowercase-kebab (e.g.

Error message

pod-template at ${path}: name must be lowercase-kebab (e.g. "sales")

What it means

Thrown by validatePodTemplate() when the 'name' field fails the regex /^[a-z][a-z0-9-]*$/. The name must start with a lowercase letter and contain only lowercase letters, digits, and hyphens (lowercase-kebab). This name is canonical and matches the BBS roomId, so strict casing is enforced.

Source

Thrown at v3/@claude-flow/cli/src/business-pods/pod-schema.ts:193

// time. We only catch obviously malformed values here.
const CRON_RE = /^([\d*/,\-]+\s+){4,5}[\d*/,\-]+$/;

/**
 * Validate `json` and return a typed `PodTemplate`. Throws
 * `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,

View on GitHub (pinned to 6b01dc5a68)

Solutions

  1. Change the 'name' field to lowercase-kebab (e.g. 'sales', 'lead-gen', 'hr-onboarding')
  2. Ensure the name starts with a lowercase letter a-z, not a digit or hyphen
  3. Replace any underscores with hyphens

Example fix

// before
{ "name": "Sales_Pipeline", ... }

// after
{ "name": "sales-pipeline", ... }
Defensive patterns

Strategy: validation

Validate before calling

const NAME_RE = /^[a-z][a-z0-9-]*$/;
function isValidPodName(name: string): boolean {
  return NAME_RE.test(name);
}

if (!isValidPodName(template.name)) {
  throw new Error('name must be lowercase-kebab');
}

Type guard

function isLowercaseKebab(s: string): boolean {
  return /^[a-z][a-z0-9-]*$/.test(s);
}

Try / catch

try {
  validatePodTemplate(json);
} catch (e) {
  if (e instanceof PodTemplateValidationError && e.message.includes('name must be lowercase-kebab')) {
    // Fix the name field and retry
  }
}

Prevention

When it happens

Trigger: The pod-template JSON has a 'name' value like 'Sales', 'sales_pod', '1sales', '-sales', or 'SALES'. Any uppercase character, underscore, leading digit, or leading hyphen triggers this error.

Common situations: A copy-pasted display name was accidentally used for the machine-readable 'name' field; a pod template was authored with CamelCase or snake_case naming conventions from another system.

Related errors


AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12). Data as JSON: /api/errors/47078cc4c0a5afbb. Report an issue: GitHub.