{"record":{"id":"e832b5bb42680bf5","repo":"sickn33/agentic-awesome-skills","slug":"range-lo-hi-out-of-bounds-for-fielddef-nam","errorCode":null,"errorMessage":"Range ${lo}-${hi} out of bounds for ${fieldDef.name} (${fieldDef.min}-${fieldDef.max})","messagePattern":"Range (.+?)-(.+?) out of bounds for (.+?) \\((.+?)-(.+?)\\)","errorType":"validation","errorClass":"CronError","httpStatus":null,"severity":"error","filePath":"skills/cron-doctor/scripts/cron-engine.js","lineNumber":159,"sourceCode":"    return;\n  }\n\n  const v = parseSingleNum(t, fieldDef, fieldIndex);\n  addOne(values, v, fieldDef, fieldIndex);\n}\n\nfunction addOne(values, v, fieldDef, fieldIndex) {\n  if (fieldDef.key === 'dow' && v === 7) { values.add(0); return; }\n  if (v < fieldDef.min || v > fieldDef.max) {\n    throw new CronError(`Value ${v} out of range for ${fieldDef.name} (${fieldDef.min}-${fieldDef.max})`, fieldIndex);\n  }\n  values.add(v);\n}\n\nfunction addRange(values, lo, hi, fieldDef) {\n  if (lo > hi) [lo, hi] = [hi, lo];\n  if (lo < fieldDef.min || hi > fieldDef.max) {\n    throw new CronError(`Range ${lo}-${hi} out of bounds for ${fieldDef.name} (${fieldDef.min}-${fieldDef.max})`, -1);\n  }\n  for (let v = lo; v <= hi; v++) {\n    if (fieldDef.key === 'dow' && v === 7) { values.add(0); continue; }\n    values.add(v);\n  }\n}\n\n// ---- Full expression parser ----\nfunction parseCron(expr) {\n  const parts = String(expr).trim().split(/\\s+/);\n  if (parts.length !== 5) {\n    throw new CronError(`Expected 5 fields (got ${parts.length}). Format: minute hour day-of-month month day-of-week`, -1);\n  }\n  const parsed = {};\n  for (let i = 0; i < 5; i++) {\n    parsed[FIELDS[i].key] = parseField(parts[i], FIELDS[i], i);\n  }\n  parsed.domRestricted = !/^\\s*\\*\\s*$/.test(parts[2]);","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/sickn33/agentic-awesome-skills/blob/58d857988fcfac6986206bca2b2fe223aa437e4b/skills/cron-doctor/scripts/cron-engine.js#L141-L177","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)"],"exampleFix":"// before\n'0 0 * 0-11 *'  // month 0 invalid\n\n// after\n'0 0 * 1-12 *'","handlingStrategy":"validation","validationCode":"const BOUNDS = [[0,59],[0,23],[1,31],[1,12],[0,6]];\nconst fields = String(expr).trim().split(/\\s+/);\nconst ok = fields.length === 5 && fields.every((f, i) =>\n  f.split(',').every(t => {\n    const m = t.match(/^(\\d+)\\s*-\\s*(\\d+)$/);\n    if (!m) return true;\n    const lo = Math.min(+m[1], +m[2]), hi = Math.max(+m[1], +m[2]);\n    return lo >= BOUNDS[i][0] && hi <= BOUNDS[i][1];\n  }));\nif (!ok) throw new Error('Range out of bounds');","typeGuard":null,"tryCatchPattern":"try { parseCron(expr); } catch (e) { if (e instanceof CronError && /out of bounds/.test(e.message)) highlightField(e.message); else throw e; }","preventionTips":["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"],"tags":["cron","range-check","validation"],"backgroundTag":"cron-expression-invalid","analyzedSha":"58d857988fcfac6986206bca2b2fe223aa437e4b","analyzedAt":"2026-08-26T11:55:59.350Z","schemaVersion":2},"datasetVersion":"2026-08-26T14:46:13.012Z"}