sickn33/agentic-awesome-skills · error · CronError
Range ${lo}-${hi} out of bounds for ${fieldDef.name} (${fiel
Error message
Range ${lo}-${hi} out of bounds for ${fieldDef.name} (${fieldDef.min}-${fieldDef.max}) What it means
addRange validates that both endpoints of a range lie within field bounds after swapping reversed order (lo>hi is normalized, not an error). It throws when either endpoint is below min or above max. The same function expands '*', so a corrupted field definition could also trip it, but in practice only explicit bad ranges do.
Source
Thrown at skills/cron-doctor/scripts/cron-engine.js:159
return;
}
const v = parseSingleNum(t, fieldDef, fieldIndex);
addOne(values, v, fieldDef, fieldIndex);
}
function addOne(values, v, fieldDef, fieldIndex) {
if (fieldDef.key === 'dow' && v === 7) { values.add(0); return; }
if (v < fieldDef.min || v > fieldDef.max) {
throw new CronError(`Value ${v} out of range for ${fieldDef.name} (${fieldDef.min}-${fieldDef.max})`, fieldIndex);
}
values.add(v);
}
function addRange(values, lo, hi, fieldDef) {
if (lo > hi) [lo, hi] = [hi, lo];
if (lo < fieldDef.min || hi > fieldDef.max) {
throw new CronError(`Range ${lo}-${hi} out of bounds for ${fieldDef.name} (${fieldDef.min}-${fieldDef.max})`, -1);
}
for (let v = lo; v <= hi; v++) {
if (fieldDef.key === 'dow' && v === 7) { values.add(0); continue; }
values.add(v);
}
}
// ---- Full expression parser ----
function parseCron(expr) {
const parts = String(expr).trim().split(/\s+/);
if (parts.length !== 5) {
throw new CronError(`Expected 5 fields (got ${parts.length}). Format: minute hour day-of-month month day-of-week`, -1);
}
const parsed = {};
for (let i = 0; i < 5; i++) {
parsed[FIELDS[i].key] = parseField(parts[i], FIELDS[i], i);
}
parsed.domRestricted = !/^\s*\*\s*$/.test(parts[2]);View on GitHub (pinned to 58d857988f)
Solutions
- Fix endpoints to the bounds given in the message, e.g. hour '5-99' -> '5-23'
- Use 1-12 for month and 1-31 for dom, 0-6 for dow
- Keep ranges ordered ascending (reversed ones are auto-swapped, but ordered is clearer)
Example fix
// before '0 0 * 0-11 *' // month 0 invalid // after '0 0 * 1-12 *'
Defensive patterns
Strategy: validation
Validate before calling
const BOUNDS = [[0,59],[0,23],[1,31],[1,12],[0,6]];
const fields = String(expr).trim().split(/\s+/);
const ok = fields.length === 5 && fields.every((f, i) =>
f.split(',').every(t => {
const m = t.match(/^(\d+)\s*-\s*(\d+)$/);
if (!m) return true;
const lo = Math.min(+m[1], +m[2]), hi = Math.max(+m[1], +m[2]);
return lo >= BOUNDS[i][0] && hi <= BOUNDS[i][1];
}));
if (!ok) throw new Error('Range out of bounds'); Try / catch
try { parseCron(expr); } catch (e) { if (e instanceof CronError && /out of bounds/.test(e.message)) highlightField(e.message); else throw e; } Prevention
- Check both endpoints against the bounds printed in the message
- Unit-test schedule constants against parseCron
- Order ranges ascending even though the engine swaps them
When it happens
Trigger: Ranges like '5-99' in hour (max 23), '0-31' in dom (min 1), '0-11' in month, or dow '25-30', passed via parseCron/parseField.
Common situations: Porting cron from systems with different bounds; writing months as 0-11 like JS Date; typos such as '59-99' minutes; partial edits that change one endpoint only.
Related errors
- Value ${v} out of range for ${fieldDef.name} (${fieldDef.min
- Invalid range "${t}" in ${fieldDef.name}
- Expected 5 fields (got ${parts.length}). Format: minute hour
- Age must be positive
- ID required
AI-assisted analysis of sickn33/agentic-awesome-skills@58d857988f (2026-08-26).
Data as JSON: /api/errors/e832b5bb42680bf5.
Report an issue: GitHub.