{"record":{"id":"f2a5dc809d4357a3","repo":"jlcodes99/cockpit-tools","slug":"crontab-segment-empty","errorCode":"crontab_segment_empty","errorMessage":"crontab_segment_empty","messagePattern":"crontab_segment_empty","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/pages/WakeupTasksPage.tsx","lineNumber":537,"sourceCode":"  if (!trimmed) {\n    throw new Error('crontab_field_empty');\n  }\n\n  if (trimmed === '*') {\n    const values = new Set<number>();\n    insertCrontabRange(values, min, max, 1, normalizeDayOfWeek);\n    return { values, wildcard: true };\n  }\n\n  const values = new Set<number>();\n  const segments = trimmed.split(',');\n  if (segments.length === 0) {\n    throw new Error('crontab_field_empty');\n  }\n  segments.forEach((segment) => {\n    const normalizedSegment = segment.trim();\n    if (!normalizedSegment) {\n      throw new Error('crontab_segment_empty');\n    }\n    parseCrontabSegment(normalizedSegment, min, max, normalizeDayOfWeek, values);\n  });\n\n  if (values.size === 0) {\n    throw new Error('crontab_no_values');\n  }\n  return { values, wildcard: false };\n};\n\nconst parseCrontabExpression = (expr: string): ParsedCrontab => {\n  const parts = expr.trim().split(/\\s+/);\n  if (parts.length !== 5) {\n    throw new Error('crontab_parts_must_be_five');\n  }\n\n  return {\n    minute: parseCrontabField(parts[0], 0, 59, false),","sourceCodeStart":519,"sourceCodeEnd":555,"githubUrl":"https://github.com/jlcodes99/cockpit-tools/blob/1ed8b77992d62ca81fabf744deb0839ad361d5bf/src/pages/WakeupTasksPage.tsx#L519-L555","documentation":"Within parseCrontabField, each comma-separated segment is trimmed; if a segment is empty (e.g. a leading, trailing, or doubled comma) the parser throws 'crontab_segment_empty' rather than silently skipping it.","triggerScenarios":"A field such as '5,,10', ',5', or '5,' passed to parseCrontabField — any comma-delimited segment that trims to an empty string.","commonSituations":"Users editing a cron list in the Wakeup Tasks UI and leaving stray commas; programmatic joining of lists where some elements are empty strings (['5',''].join(',')).","solutions":["Remove stray/extra commas: '5,10' instead of '5,,10'.","Filter empty segments before building the expression: values.filter(v => v.trim()).join(',').","Pre-validate the field with a regex like /^(\\d+(-\\d+)?(\\/\\d+)?)(,(\\d+(-\\d+)?(\\/\\d+)?))*$/ and show an inline error."],"exampleFix":"// before\nconst minuteField = ['5', '', '10'].join(',');   // '5,,10'\n// after\nconst minuteField = ['5', '', '10'].filter(Boolean).join(',');  // '5,10'","handlingStrategy":"validation","validationCode":"const LIST_RE = /^(\\d+(-\\d+)?(\\/\\d+)?)(,(\\d+(-\\d+)?(\\/\\d+)?))*$/;\nconst isValidListField = (f: string) => LIST_RE.test(f.trim());","typeGuard":"const hasNoEmptySegments = (f: string): boolean =>\n  f.split(',').every((s) => s.trim().length > 0);","tryCatchPattern":"try {\n  const parsed = parseCrontabExpression(expr);\n} catch (e) {\n  if ((e as Error).message === 'crontab_segment_empty') {\n    setFieldError('remove empty items between commas in the field list');\n  }\n}","preventionTips":["Filter empty entries before joining lists: parts.filter(Boolean).join(',')","Reject leading/trailing/doubled commas in the crontab input with an inline validator","Normalize pasted crontab strings (trim, collapse whitespace) before parsing"],"tags":["validation","crontab","input-parsing"],"backgroundTag":"crontab-segment-empty","analyzedSha":"1ed8b77992d62ca81fabf744deb0839ad361d5bf","analyzedAt":"2026-09-05T09:51:41.178Z","contentChangedAt":"2026-09-05T09:51:41.178Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}