ruvnet/ruflo · error · PodTemplateValidationError

pod-template at ${path}: budgetUsdMonthly must be ≥0

Error message

pod-template at ${path}: budgetUsdMonthly must be ≥0

What it means

Thrown by validatePodTemplate() when budgetUsdMonthly is a valid finite number but is negative. The monthly budget is a hard cap on pod spending; 0 means unlimited (not recommended but allowed), while negative values are nonsensical.

Source

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

        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',
      '/',
    );
  }
  const preferLocalExecution = requireBoolean(json, 'preferLocalExecution', '/');
  const cronSchedule = requireString(json, 'cronSchedule', '/');
  if (!CRON_RE.test(cronSchedule)) {
    throw new PodTemplateValidationError(
      'cronSchedule must be a POSIX cron expression (5 or 6 fields)',
      '/',
    );

View on GitHub (pinned to 6b01dc5a68)

Solutions

  1. Set budgetUsdMonthly to 0 for unlimited, or a positive dollar amount (e.g. 500)
  2. If the intent was 'no budget', use 0 rather than a negative sentinel

Example fix

// before
{ "budgetUsdMonthly": -1 }

// after
{ "budgetUsdMonthly": 0 }
Defensive patterns

Strategy: validation

Validate before calling

if (typeof template.budgetUsdMonthly !== 'number' || template.budgetUsdMonthly < 0) {
  throw new Error('budgetUsdMonthly must be >= 0 (use 0 for unlimited)');
}

Type guard

function isValidMonthlyBudget(v: unknown): boolean {
  return typeof v === 'number' && Number.isFinite(v) && v >= 0;
}

Try / catch

try {
  validatePodTemplate(json);
} catch (e) {
  if (e instanceof PodTemplateValidationError && e.message.includes('budgetUsdMonthly')) {
    // Set budgetUsdMonthly to 0 or a positive number
  }
}

Prevention

When it happens

Trigger: The budgetUsdMonthly field is set to any negative number (e.g. -1, -100.50). The requireNumber helper already verified it is a finite number, so this is purely a sign check.

Common situations: A budget was entered as a credit or refund notation; a sign error in a calculation that produced the template; a placeholder value of -1 was used to mean 'unset'.

Related errors


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