ruvnet/ruflo · error · PodTemplateValidationError

pod-template at ${path}: field "${key}" must be an array

Error message

pod-template at ${path}: field "${key}" must be an array

What it means

Thrown by the requireArray() helper inside the pod-template schema validator. Fires when a field expected to be an array is instead a non-array value (object, string, number, null, undefined). Used for agents, allowedMcpTools (top-level), bench.successCriteria, and auditReadView.includedEventTypes.

Source

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

  if (typeof v !== 'number' || !Number.isFinite(v)) {
    throw new PodTemplateValidationError(`field "${key}" must be a finite number`, path);
  }
  return v;
}

function requireBoolean(parent: Record<string, unknown>, key: string, path: string): boolean {
  const v = parent[key];
  if (typeof v !== 'boolean') {
    throw new PodTemplateValidationError(`field "${key}" must be a boolean`, path);
  }
  return v;
}

function requireArray<T>(parent: Record<string, unknown>, key: string, path: string,
                          itemValidator: (item: unknown, ipath: string) => T): T[] {
  const v = parent[key];
  if (!Array.isArray(v)) {
    throw new PodTemplateValidationError(`field "${key}" must be an array`, path);
  }
  return v.map((item, idx) => itemValidator(item, `${path}/${key}[${idx}]`));
}

function validatePodAgent(item: unknown, path: string): PodAgent {
  if (!isObject(item)) throw new PodTemplateValidationError('agent must be an object', path);
  return {
    role: requireString(item, 'role', path),
    agentType: requireString(item, 'agentType', path),
    description: requireString(item, 'description', path),
    preferLocal: requireBoolean(item, 'preferLocal', path),
  };
}

function validatePodBench(item: unknown, path: string): PodBench {
  if (!isObject(item)) throw new PodTemplateValidationError('bench must be an object', path);
  const name = requireString(item, 'name', path);
  const description = requireString(item, 'description', path);

View on GitHub (pinned to 6b01dc5a68)

Solutions

  1. Read the error path and field name to find which field should be an array
  2. Wrap single items in square brackets, and ensure list fields are JSON arrays
  3. For allowedMcpTools and agents, provide at least one entry (empty arrays are rejected by separate downstream checks)

Example fix

// before:
"agents": { "role": "lead", ... } // object, throws

// after:
"agents": [ { "role": "lead", ... } ] // array
Defensive patterns

Strategy: validation

Validate before calling

import { validatePodTemplate, PodTemplateValidationError } from '@claude-flow/cli/business-pods/pod-schema';

try {
  const pod = validatePodTemplate(parsedJson);
} catch (e) {
  if (e instanceof PodTemplateValidationError) {
    console.error(`Array field error at ${e.path}: ${e.message}`);
  }
}

Try / catch

import { validatePodTemplate, PodTemplateValidationError } from '@claude-flow/cli/business-pods/pod-schema';

try {
  const pod = validatePodTemplate(raw);
} catch (e) {
  if (e instanceof PodTemplateValidationError) {
    console.error(e.message);
    process.exit(1);
  }
  throw e;
}

Prevention

When it happens

Trigger: validatePodTemplate() encounters a field that requireArray() reads and the value is not recognized by Array.isArray() — e.g., a single object instead of a list, a comma-separated string, or a missing field (undefined).

Common situations: A single agent written as an object instead of wrapped in an array; allowedMcpTools written as a comma-separated string; a missing array field; a value accidentally set to null.

Related errors


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