{"record":{"id":"8ebf92e553bce660","repo":"robfig/cron","slug":"failed-to-parse-duration-s-s","errorCode":null,"errorMessage":"failed to parse duration %s: %s","messagePattern":"failed to parse duration (.+?): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"parser.go","lineNumber":428,"sourceCode":"\n\tcase \"@hourly\":\n\t\treturn &SpecSchedule{\n\t\t\tSecond:   1 << seconds.min,\n\t\t\tMinute:   1 << minutes.min,\n\t\t\tHour:     all(hours),\n\t\t\tDom:      all(dom),\n\t\t\tMonth:    all(months),\n\t\t\tDow:      all(dow),\n\t\t\tLocation: loc,\n\t\t}, nil\n\n\t}\n\n\tconst every = \"@every \"\n\tif strings.HasPrefix(descriptor, every) {\n\t\tduration, err := time.ParseDuration(descriptor[len(every):])\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to parse duration %s: %s\", descriptor, err)\n\t\t}\n\t\treturn Every(duration), nil\n\t}\n\n\treturn nil, fmt.Errorf(\"unrecognized descriptor: %s\", descriptor)\n}\n","sourceCodeStart":410,"sourceCodeEnd":435,"githubUrl":"https://github.com/robfig/cron/blob/bc59245fe10efaed9d51b56900192527ed733435/parser.go#L410-L435","documentation":"Thrown by parseDescriptor in parser.go when a descriptor starting with the '@every ' prefix has a suffix that time.ParseDuration cannot parse. The remainder after '@every ' must be a valid Go duration string such as '1h30m' or '15m'. The underlying ParseDuration error is embedded in the message.","triggerScenarios":"Calling cron.Parse with '@every xyz', '@every 5', '@every 5min' (Go durations require 'm' for minutes, not 'min'... actually 'min' is invalid; must be 'm'), '@every 1d' (days are not a Go duration unit), or '@every' followed by an empty/whitespace suffix.","commonSituations":"Users writing human-style durations ('1d', '5min', '2w') that Go's duration syntax doesn't accept; config values with missing units ('@every 30'); localizing the string so the prefix matches but the number doesn't; Go version migrations are irrelevant here — the unit set is fixed by time.ParseDuration.","solutions":["Use a valid Go duration string: units are ns, us, ms, s, m, h (e.g. '@every 1h30m')","Convert days/weeks yourself: '@every 24h' for daily, '@every 168h' for weekly","Validate the duration from config with time.ParseDuration before embedding it in the descriptor","If you need '1d' style syntax, write a wrapper that translates human durations to Go durations before calling Parse"],"exampleFix":"// before\ncron.Parse(\"@every 1d\") // 'd' is not a Go duration unit\n// after\ncron.Parse(\"@every 24h\")","handlingStrategy":"validation","validationCode":"if strings.HasPrefix(spec, \"@every \") {\n\tif _, err := time.ParseDuration(strings.TrimPrefix(spec, \"@every \")); err != nil {\n\t\treturn fmt.Errorf(\"invalid @every duration: %w\", err)\n\t}\n}","typeGuard":null,"tryCatchPattern":"sched, err := cron.Parse(spec)\nif err != nil {\n\treturn fmt.Errorf(\"invalid cron spec %q: %w\", spec, err)\n}","preventionTips":["Use only Go duration units: ns, us, ms, s, m, h — never 'd' or 'w'","Test duration config values with time.ParseDuration at load time","Convert human units (days, weeks) to hours before building the descriptor"],"tags":["cron","duration","descriptor","go"],"backgroundTag":"invalid-duration-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"}