ruvnet/ruflo · error · PodTemplateValidationError
reservationExpiryMs must be within [5000, 300000] ms (ADR-16
Error message
reservationExpiryMs must be within [5000, 300000] ms (ADR-164.1 §3.2)
What it means
Thrown by validatePodTemplate() when the optional 'reservationExpiryMs' field is present but outside the bounded range [5000, 300000] milliseconds (5 seconds to 5 minutes), per ADR-164.1 §3.2. This value controls the atomic budget tracker's reservation expiry. If the field is absent entirely, no error is thrown and a default of 60000 ms is used.
Source
Thrown at v3/@claude-flow/cli/src/business-pods/pod-schema.ts:256
'/',
);
}
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)',
'/',
);
}
const auditReadView = validateAuditReadView(json.auditReadView, '/auditReadView');
let reservationExpiryMs: number | undefined;
if (json.reservationExpiryMs !== undefined) {
const v = requireNumber(json, 'reservationExpiryMs', '/');
// ADR-164.1 §3.2 — bounded to [5_000, 300_000] ms.
if (v < 5_000 || v > 300_000) {
throw new PodTemplateValidationError(
'reservationExpiryMs must be within [5000, 300000] ms (ADR-164.1 §3.2)',
'/',
);
}
reservationExpiryMs = v;
}
return {
name,
displayName,
roomId,
agents,
allowedMcpTools,
bench,
piiPolicy: piiPolicy as PiiPolicy,
budgetUsdMonthly,
budgetUsdPerRun,
preferLocalExecution,View on GitHub (pinned to 6b01dc5a68)
Solutions
- Set reservationExpiryMs to a value between 5000 and 300000 (inclusive)
- Or remove the field entirely to use the default 60000 ms (60 seconds)
- Double-check the unit is milliseconds, not seconds
Example fix
// before
{ "reservationExpiryMs": 60 }
// after
{ "reservationExpiryMs": 60000 } Defensive patterns
Strategy: validation
Validate before calling
const MIN_EXPIRY = 5000;
const MAX_EXPIRY = 300000;
if (template.reservationExpiryMs !== undefined) {
if (template.reservationExpiryMs < MIN_EXPIRY || template.reservationExpiryMs > MAX_EXPIRY) {
throw new Error(`reservationExpiryMs must be within [${MIN_EXPIRY}, ${MAX_EXPIRY}] ms`);
}
} Type guard
function isValidReservationExpiry(v: unknown): boolean {
return v === undefined || (typeof v === 'number' && Number.isFinite(v) && v >= 5000 && v <= 300000);
} Try / catch
try {
validatePodTemplate(json);
} catch (e) {
if (e instanceof PodTemplateValidationError && e.message.includes('reservationExpiryMs')) {
// Remove the field to use default 60000ms, or set to [5000, 300000]
}
} Prevention
- Remember the unit is milliseconds, not seconds
- Omit the field entirely to use the default 60000ms (60s)
- The valid range is 5 seconds (5000ms) to 5 minutes (300000ms) per ADR-164.1 §3.2
When it happens
Trigger: The pod-template JSON includes "reservationExpiryMs" with a value less than 5000 (e.g. 1000) or greater than 300000 (e.g. 600000). If the field is omitted entirely, this check is never reached.
Common situations: A value was set in milliseconds but intended as seconds (e.g. 60 meaning 60 seconds but interpreted as 60ms — below the 5000 floor); a value was copied from a different system with a different expiry window.
Related errors
- pod-template at ${path}: budgetUsdMonthly must be ≥0
- pod-template at ${path}: budgetUsdPerRun must be ≥0
- pod-template at ${path}: budgetUsdPerRun must not exceed bud
- budgetUsdPerRun must not exceed budgetUsdMonthly
- pod-template at ${path}: field "${key}" must be a non-empty
AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12).
Data as JSON: /api/errors/9b672140befca65a.
Report an issue: GitHub.