jlcodes99/cockpit-tools · error

crontab_parts_must_be_five

crontab_parts_must_be_five

Error message

crontab_parts_must_be_five

What it means

parseCrontabExpression splits the trimmed expression on whitespace and requires exactly five fields (minute hour day-of-month month day-of-week). Any other count — too few or too many — throws 'crontab_parts_must_be_five'; six/eight-field cron dialects with seconds or years are not supported.

Source

Thrown at src/pages/WakeupTasksPage.tsx:551

  }
  segments.forEach((segment) => {
    const normalizedSegment = segment.trim();
    if (!normalizedSegment) {
      throw new Error('crontab_segment_empty');
    }
    parseCrontabSegment(normalizedSegment, min, max, normalizeDayOfWeek, values);
  });

  if (values.size === 0) {
    throw new Error('crontab_no_values');
  }
  return { values, wildcard: false };
};

const parseCrontabExpression = (expr: string): ParsedCrontab => {
  const parts = expr.trim().split(/\s+/);
  if (parts.length !== 5) {
    throw new Error('crontab_parts_must_be_five');
  }

  return {
    minute: parseCrontabField(parts[0], 0, 59, false),
    hour: parseCrontabField(parts[1], 0, 23, false),
    dayOfMonth: parseCrontabField(parts[2], 1, 31, false),
    month: parseCrontabField(parts[3], 1, 12, false),
    dayOfWeek: parseCrontabField(parts[4], 0, 7, true),
  };
};

const isCrontabMatch = (parsed: ParsedCrontab, date: Date): boolean => {
  const minute = date.getMinutes();
  const hour = date.getHours();
  const dayOfMonth = date.getDate();
  const month = date.getMonth() + 1;
  const dayOfWeek = date.getDay();

View on GitHub (pinned to 1ed8b77992)

Solutions

  1. Convert the expression to standard 5-field cron: drop the seconds field and replace Quartz '?' with '*'.
  2. If seconds precision is needed, note it is unsupported; move the sub-minute logic into the scheduler, not the cron string.
  3. Trim stray whitespace/tokens and ensure exactly five space-separated fields: '*/5 * * * *'.
  4. Validate with parseCrontabExpression in a try/catch before save and show the code to the user.

Example fix

// before
'0 0/5 * * * ?'      // Quartz 6-field
// after
'*/5 * * * *'        // standard 5-field cron
Defensive patterns

Strategy: validation

Validate before calling

const isFiveFieldCron = (expr: string): boolean =>
  expr.trim().split(/\s+/).length === 5;
// additionally reject Quartz '?' and seconds field before parsing

Type guard

const isStandardCron = (expr: unknown): expr is string =>
  typeof expr === 'string' && expr.trim().split(/\s+/).length === 5 && !expr.includes('?');

Try / catch

try {
  const parsed = parseCrontabExpression(expr);
} catch (e) {
  if ((e as Error).message === 'crontab_parts_must_be_five') {
    setFieldError('use standard 5-field cron (minute hour dom month dow)');
  }
}

Prevention

When it happens

Trigger: parseCrontabExpression called with '*/5 * * *' (4 fields), '* * * * * *' (6 fields, e.g. a Quartz or seconds-precision cron), or an empty string (split gives ['']).

Common situations: Pasting a Quartz expression ('0 0/5 * * * ?') or a systemd/6-field cron into the Wakeup Tasks crontab input; an empty crontab field on the form; trailing comments or extra tokens counted as fields.

Related errors


AI-assisted analysis of jlcodes99/cockpit-tools@1ed8b77992 (2026-09-05). Data as JSON: /api/errors/d67069ddd8ab1393. Report an issue: GitHub.