{"record":{"id":"1b6f4a060e7b06dd","repo":"sickn33/agentic-awesome-skills","slug":"expected-5-fields-got-parts-length-format-m","errorCode":null,"errorMessage":"Expected 5 fields (got ${parts.length}). Format: minute hour day-of-month month day-of-week","messagePattern":"Expected 5 fields \\(got (.+?)\\)\\. Format: minute hour day-of-month month day-of-week","errorType":"validation","errorClass":"CronError","httpStatus":null,"severity":"error","filePath":"skills/cron-doctor/scripts/cron-engine.js","lineNumber":171,"sourceCode":"  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]);\n  parsed.dowRestricted = !/^\\s*\\*\\s*$/.test(parts[4]);\n  parsed.parts = parts;\n  return parsed;\n}\n\n// ---- Human-readable description ----\nfunction describe(expr) {\n  let parsed;\n  try { parsed = parseCron(expr); } catch (e) { return { text: e.message, error: true }; }\n  return { text: describeParsed(parsed), error: false, parsed };\n}\n","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/sickn33/agentic-awesome-skills/blob/58d857988fcfac6986206bca2b2fe223aa437e4b/skills/cron-doctor/scripts/cron-engine.js#L153-L189","documentation":"parseCron splits the expression on whitespace and requires exactly 5 fields: minute hour day-of-month month day-of-week. Any other count is rejected immediately. This engine does not support a 6th seconds field, a year field, or @shorthands like @daily.","triggerScenarios":"Passing a 6-field expression with seconds ('0 0 0 * * *'), a 7-field Quartz-style cron, '@daily'/'@hourly'/'@reboot' strings, or an expression with a missing field ('0 0 * *').","commonSituations":"Copying a Quartz (7 fields) or Spring (6 fields) cron into a standard 5-field tool; assuming @ macros exist; accidentally deleting a field while editing.","solutions":["Reduce to exactly 5 fields: drop a leading seconds field or trailing year","Replace @shorthands manually: @daily -> '0 0 * * *', @hourly -> '0 * * * *'","Count whitespace-separated tokens; the message reports how many were found"],"exampleFix":"// before\n'0 30 9 * * *'  // 6 fields (seconds first)\n\n// after\n'30 9 * * *'    // 5 fields","handlingStrategy":"validation","validationCode":"const n = String(expr).trim().split(/\\s+/).filter(Boolean).length;\nif (n !== 5) throw new Error(`Expected 5 fields, got ${n}`);\nconst parsed = parseCron(expr);","typeGuard":null,"tryCatchPattern":"try { parseCron(expr); } catch (e) { if (e instanceof CronError && /Expected 5 fields/.test(e.message)) promptForFiveFieldCron(expr); else throw e; }","preventionTips":["Normalize @daily/@hourly to 5-field equivalents before parsing","Strip a leading seconds field when importing Quartz/Spring cron","Validate user-entered schedules client-side before saving"],"tags":["cron","parsing","validation"],"backgroundTag":"cron-expression-invalid","analyzedSha":"58d857988fcfac6986206bca2b2fe223aa437e4b","analyzedAt":"2026-08-26T11:55:59.350Z","schemaVersion":2},"datasetVersion":"2026-08-26T14:46:13.012Z"}