{"record":{"id":"94907e32c4edb816","repo":"ruvnet/ruflo","slug":"field-key-must-be-an-array","errorCode":null,"errorMessage":"field \"${key}\" must be an array","messagePattern":"field \"(.+?)\" must be an array","errorType":"validation","errorClass":"PodTemplateValidationError","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/business-pods/pod-schema.ts","lineNumber":121,"sourceCode":"  if (typeof v !== 'number' || !Number.isFinite(v)) {\n    throw new PodTemplateValidationError(`field \"${key}\" must be a finite number`, path);\n  }\n  return v;\n}\n\nfunction requireBoolean(parent: Record<string, unknown>, key: string, path: string): boolean {\n  const v = parent[key];\n  if (typeof v !== 'boolean') {\n    throw new PodTemplateValidationError(`field \"${key}\" must be a boolean`, path);\n  }\n  return v;\n}\n\nfunction requireArray<T>(parent: Record<string, unknown>, key: string, path: string,\n                          itemValidator: (item: unknown, ipath: string) => T): T[] {\n  const v = parent[key];\n  if (!Array.isArray(v)) {\n    throw new PodTemplateValidationError(`field \"${key}\" must be an array`, path);\n  }\n  return v.map((item, idx) => itemValidator(item, `${path}/${key}[${idx}]`));\n}\n\nfunction validatePodAgent(item: unknown, path: string): PodAgent {\n  if (!isObject(item)) throw new PodTemplateValidationError('agent must be an object', path);\n  return {\n    role: requireString(item, 'role', path),\n    agentType: requireString(item, 'agentType', path),\n    description: requireString(item, 'description', path),\n    preferLocal: requireBoolean(item, 'preferLocal', path),\n  };\n}\n\nfunction validatePodBench(item: unknown, path: string): PodBench {\n  if (!isObject(item)) throw new PodTemplateValidationError('bench must be an object', path);\n  const name = requireString(item, 'name', path);\n  const description = requireString(item, 'description', path);","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/cli/src/business-pods/pod-schema.ts#L103-L139","documentation":"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.","triggerScenarios":"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.","commonSituations":"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'.","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"],"exampleFix":"// before\n{ \"allowedMcpTools\": \"web_search\" }\n// after\n{ \"allowedMcpTools\": [\"web_search\"] }","handlingStrategy":"validation","validationCode":"function isStringArrayField(o: Record<string, unknown>, key: string): boolean {\n  return Array.isArray(o[key]);\n}\nfor (const k of ['agents', 'allowedMcpTools']) {\n  if (!isStringArrayField(template, k)) fail(`${k} must be a JSON array, e.g. [\"web_search\"]`);\n}","typeGuard":"function isUnknownArray(v: unknown): v is unknown[] {\n  return Array.isArray(v);\n}","tryCatchPattern":"try {\n  validatePodTemplate(template);\n} catch (e) {\n  if (e instanceof PodTemplateValidationError && e.message.includes('must be an array')) {\n    fail(`Wrap ${e.path} in [ ... ] — single values are not accepted`);\n  } else throw e;\n}","preventionTips":["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"],"tags":["pod","schema","validation","json","arrays"],"backgroundTag":"schema-validation-failed","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}