{"record":{"id":"1ce687e1a60b674b","repo":"robfig/cron","slug":"expected-exactly-d-fields-found-d-s","errorCode":null,"errorMessage":"expected exactly %d fields, found %d: %s","messagePattern":"expected exactly (.+?) fields, found (.+?): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"parser.go","lineNumber":187,"sourceCode":"\t\toptionals++\n\t}\n\tif optionals > 1 {\n\t\treturn nil, fmt.Errorf(\"multiple optionals may not be configured\")\n\t}\n\n\t// Figure out how many fields we need\n\tmax := 0\n\tfor _, place := range places {\n\t\tif options&place > 0 {\n\t\t\tmax++\n\t\t}\n\t}\n\tmin := max - optionals\n\n\t// Validate number of fields\n\tif count := len(fields); count < min || count > max {\n\t\tif min == max {\n\t\t\treturn nil, fmt.Errorf(\"expected exactly %d fields, found %d: %s\", min, count, fields)\n\t\t}\n\t\treturn nil, fmt.Errorf(\"expected %d to %d fields, found %d: %s\", min, max, count, fields)\n\t}\n\n\t// Populate the optional field if not provided\n\tif min < max && len(fields) == min {\n\t\tswitch {\n\t\tcase options&DowOptional > 0:\n\t\t\tfields = append(fields, defaults[5]) // TODO: improve access to default\n\t\tcase options&SecondOptional > 0:\n\t\t\tfields = append([]string{defaults[0]}, fields...)\n\t\tdefault:\n\t\t\treturn nil, fmt.Errorf(\"unknown optional field\")\n\t\t}\n\t}\n\n\t// Populate all fields not part of options with their defaults\n\tn := 0","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/robfig/cron/blob/bc59245fe10efaed9d51b56900192527ed733435/parser.go#L169-L205","documentation":"normalizeFields validates that the whitespace-split spec has exactly the number of fields the configured options require. When the parser has no optional fields, min==max, and a field count other than that exact number fails with this error listing expected, found, and the raw fields.","triggerScenarios":"Parsing a 5-field spec with a Parser configured for 6 fields (Second enabled) or vice versa; passing \"* * * *\" (4 fields) to a standard 5-field parser.","commonSituations":"Copying Linux crontab 5-field expressions into a seconds-enabled parser; omitting the day-of-month or month field by mistake; specs built by joining user inputs where empty parts collapse.","solutions":["Adjust the spec to the field count the parser expects (add/remove a seconds field)","Reconfigure NewParser options to match the field count of your specs (enable SecondOptional for both 5/6 fields)","Normalize the spec (pad defaults) before calling Parse"],"exampleFix":"// before\np := cron.NewParser(cron.Second | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow)\ns, err := p.Parse(\"0 5 * * 1\") // 5 fields, parser wants 6\n// after\ns, err := p.Parse(\"0 0 5 * * 1\") // seconds added\n// or\np := cron.NewParser(cron.SecondOptional | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow)","handlingStrategy":"validation","validationCode":"fields := strings.Fields(spec)\nif len(fields) != 5 && len(fields) != 6 {\n\treturn fmt.Errorf(\"cron spec must have 5 or 6 fields, got %d\", len(fields))\n}","typeGuard":null,"tryCatchPattern":"sched, err := parser.Parse(spec)\nif err != nil {\n\treturn fmt.Errorf(\"invalid cron spec %q: %w\", spec, err)\n}","preventionTips":["Match spec field count to parser options (seconds vs no seconds)","Use SecondOptional to accept both 5- and 6-field specs","Normalize/pad specs before calling Parse"],"tags":["go","cron","parser","validation","field-count"],"backgroundTag":"invalid-argument-format","analyzedSha":"bc59245fe10efaed9d51b56900192527ed733435","analyzedAt":"2026-09-07T00:35:06.760Z","contentChangedAt":"2026-09-07T00:35:06.760Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}