ruvnet/ruflo · error · PodTemplateValidationError
field "${key}" must be an array
Error message
field "${key}" must be an array What it means
Pod template validator's requireArray() throws PodTemplateValidationError when a required array field is missing or not an array. Covers agents, allowedMcpTools, bench.successCriteria, and auditReadView.includedEventTypes. Item-level validation happens after this check, so a wrong container type fails here first.
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 fa13ee4ad6)
Solutions
- Wrap values in JSON arrays: "allowedMcpTools": ["web_search"], "agents": [ {...} ]
- Use [] for an intentional empty list (note: bench.successCriteria additionally requires ≥1 entry)
- Check the named field at the error's path and fix its container type
- Run templates through validatePodTemplate in CI
Example fix
// before
{ "allowedMcpTools": "web_search" }
// after
{ "allowedMcpTools": ["web_search"] } Defensive patterns
Strategy: validation
Validate before calling
function isStringArrayField(o: Record<string, unknown>, key: string): boolean {
return Array.isArray(o[key]);
}
for (const k of ['agents', 'allowedMcpTools']) {
if (!isStringArrayField(template, k)) fail(`${k} must be a JSON array, e.g. ["web_search"]`);
} Type guard
function isUnknownArray(v: unknown): v is unknown[] {
return Array.isArray(v);
} Try / catch
try {
validatePodTemplate(template);
} catch (e) {
if (e instanceof PodTemplateValidationError && e.message.includes('must be an array')) {
fail(`Wrap ${e.path} in [ ... ] — single values are not accepted`);
} else throw e;
} Prevention
- Never use single-item shorthand for list fields; always bracket them
- Use [] (or ensure ≥1 entry where required) rather than null for 'empty'
- Validate container types before item types — the validator reports the container first
When it happens
Trigger: validatePodTemplate() with "agents" as an object or string instead of a list, "allowedMcpTools": "*" (single string instead of ["*"]), successCriteria as a string, or the key missing. The failing key name is in the message.
Common situations: Single-item shorthand ("allowedMcpTools": "web_search" instead of ["web_search"]); YAML block scalars producing a string; templates edited by hand where brackets were dropped; null used to mean 'none'.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- field "${key}" must be a non-empty string
- field "${key}" must be a finite number
- field "${key}" must be a boolean
- agent must be an object
- bench must be an object
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/94907e32c4edb816.
Report an issue: GitHub.