ruvnet/ruflo · error · PodTemplateValidationError

pod-template at ${path}: piiPolicy must be one of: ${PII_POL

Error message

pod-template at ${path}: piiPolicy must be one of: ${PII_POLICIES.join(', ')}

What it means

Thrown by validatePodTemplate() when the 'piiPolicy' field is not one of the four allowed values: 'soc2', 'gdpr', 'hipaa', 'permissive'. This policy is applied to every envelope entering or leaving the pod's BBS room, so only enumerated compliance modes are accepted.

Source

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

  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) {
    throw new PodTemplateValidationError('allowedMcpTools must have ≥1 entry', '/');
  }
  const bench = validatePodBench(json.bench, '/bench');
  const piiPolicy = requireString(json, 'piiPolicy', '/');
  if (!PII_POLICIES.includes(piiPolicy as PiiPolicy)) {
    throw new PodTemplateValidationError(
      `piiPolicy must be one of: ${PII_POLICIES.join(', ')}`,
      '/',
    );
  }
  const budgetUsdMonthly = requireNumber(json, 'budgetUsdMonthly', '/');
  if (budgetUsdMonthly < 0) {
    throw new PodTemplateValidationError('budgetUsdMonthly must be ≥0', '/');
  }
  const budgetUsdPerRun = requireNumber(json, 'budgetUsdPerRun', '/');
  if (budgetUsdPerRun < 0) {
    throw new PodTemplateValidationError('budgetUsdPerRun must be ≥0', '/');
  }
  if (budgetUsdMonthly > 0 && budgetUsdPerRun > budgetUsdMonthly) {
    throw new PodTemplateValidationError(
      'budgetUsdPerRun must not exceed budgetUsdMonthly',
      '/',
    );
  }

View on GitHub (pinned to 6b01dc5a68)

Solutions

  1. Set piiPolicy to exactly one of: 'soc2', 'gdpr', 'hipaa', 'permissive' (all lowercase)
  2. Use 'permissive' for non-regulated internal pods
  3. Double-check spelling: 'hipaa' not 'hippa'

Example fix

// before
{ "piiPolicy": "SOC2" }

// after
{ "piiPolicy": "soc2" }
Defensive patterns

Strategy: validation

Validate before calling

const VALID_PII_POLICIES = ['soc2', 'gdpr', 'hipaa', 'permissive'] as const;
type PiiPolicy = typeof VALID_PII_POLICIES[number];

function isPiiPolicy(s: string): s is PiiPolicy {
  return (VALID_PII_POLICIES as readonly string[]).includes(s);
}

if (!isPiiPolicy(template.piiPolicy)) {
  throw new Error(`piiPolicy must be one of: ${VALID_PII_POLICIES.join(', ')}`);
}

Type guard

const PII_POLICIES = ['soc2', 'gdpr', 'hipaa', 'permissive'] as const;
function isPiiPolicy(s: unknown): s is typeof PII_POLICIES[number] {
  return typeof s === 'string' && (PII_POLICIES as readonly string[]).includes(s);
}

Try / catch

try {
  validatePodTemplate(json);
} catch (e) {
  if (e instanceof PodTemplateValidationError && e.message.includes('piiPolicy')) {
    // Set piiPolicy to one of: soc2, gdpr, hipaa, permissive
  }
}

Prevention

When it happens

Trigger: The piiPolicy field is a string but does not exactly match one of the four allowed values. Examples: 'SOC2' (wrong case), 'gdpr-strict', 'pci', 'none', or a typo like 'hippa'.

Common situations: Case mismatch ('SOC2' instead of 'soc2'); a custom policy name was invented instead of using the enumerated set; a typo in 'hipaa' (commonly misspelled 'hippa').

Related errors


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