ruvnet/ruflo · error · PodTemplateValidationError
pod-template at ${path}: auditReadView.retentionDays must be
Error message
pod-template at ${path}: auditReadView.retentionDays must be ≥1 What it means
Thrown inside validateAuditReadView() after requireNumber() confirms retentionDays is a finite number. Fires when that number is less than 1 (zero, negative, or fractional). retentionDays defines how long audit events are kept in the business-owner read view; a sub-day retention is rejected as it would drop events before they can be reviewed.
Source
Thrown at v3/@claude-flow/cli/src/business-pods/pod-schema.ts:168
if (scheduleHours < 1) {
throw new PodTemplateValidationError('bench.scheduleHours must be ≥1', path);
}
return { name, description, successCriteria, scheduleHours };
}
function validateAuditReadView(item: unknown, path: string): PodAuditReadView {
if (!isObject(item)) {
throw new PodTemplateValidationError('auditReadView must be an object', path);
}
const includedEventTypes = requireArray(item, 'includedEventTypes', path, (s, sp) => {
if (typeof s !== 'string' || s.length === 0) {
throw new PodTemplateValidationError('includedEventTypes entries must be non-empty strings', sp);
}
return s;
});
const retentionDays = requireNumber(item, 'retentionDays', path);
if (retentionDays < 1) {
throw new PodTemplateValidationError('auditReadView.retentionDays must be ≥1', path);
}
return { includedEventTypes, retentionDays };
}
// POSIX cron — five or six space-separated fields. Permissive on field
// contents (digits, *, -, /, ,) — actual cron evaluation happens at schedule
// time. We only catch obviously malformed values here.
const CRON_RE = /^([\d*/,\-]+\s+){4,5}[\d*/,\-]+$/;
/**
* Validate `json` and return a typed `PodTemplate`. Throws
* `PodTemplateValidationError` with a JSON-pointer-style path on failure.
*
* Used by:
* - `business_pod_validate` MCP tool — returns the error verbatim
* - `pod-tick.mjs` — pre-flight check before any pod execution
* - any external schema-loader that wants typed templates
*/View on GitHub (pinned to 6b01dc5a68)
Solutions
- Set auditReadView.retentionDays to an integer >= 1 (e.g., 90 for a standard compliance window)
- Align the value with the piiPolicy in effect — HIPAA/gdpr may mandate specific minimum retention periods
Example fix
// before: "retentionDays": 0 // throws // after: "retentionDays": 90 // 90-day compliance window
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(`retentionDays 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
- Set auditReadView.retentionDays to an integer >= 1 (e.g., 90 for a standard compliance window)
- Align retention with the piiPolicy — HIPAA/gdpr may mandate longer minimums
- Validate templates with validatePodTemplate() in CI
When it happens
Trigger: validateAuditReadView() reads auditReadView.retentionDays, requireNumber() passes (finite number), but the value is < 1.
Common situations: retentionDays set to 0 (disable audit retention); a fractional value; a negative number from a misconfigured default; confusion between days and hours.
Related errors
- pod-template at ${path}: field "${key}" must be a finite num
- pod-template at ${path}: bench.scheduleHours must be ≥1
- pod-template at ${path}: auditReadView must be an object
- pod-template at ${path}: includedEventTypes entries must be
- selectAgentBackend: pod.budgetUsdMonthly must be a finite nu
AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12).
Data as JSON: /api/errors/e7a878799d4426f7.
Report an issue: GitHub.