robfig/cron · error
beginning of range ( ) below minimum ( )
Error message
beginning of range (%d) below minimum (%d): %s
What it means
Thrown by getRange in parser.go when the start value of a cron field range is below the field's minimum. Each cron field (second, minute, hour, dom, month, dow) has a bounds struct with a min/max, and getRange validates the parsed range against those bounds before building the bit set. E.g. a range starting at 0 in the day-of-month or month field (both 1-based) fails because their minimum is 1.
Solutions
- Read the error's 'below minimum (%d)' value to see the field's floor (e.g. 1 for month/dom) and change the range start to that minimum or higher
- Use '*' or '?' instead of an explicit range when you mean the full field
- If generating specs in code, clamp the range start to the field's bounds before formatting the string
- Remember this library's month and day-of-month fields are 1-based, unlike some 0-based APIs
Example fix
// before
cron.Parse("0 0 0 0-15 * *") // dom min is 1
// after
cron.Parse("0 0 0 1-15 * *") Defensive patterns
Strategy: validation
Validate before calling
func validRangeStart(start, fieldMin int) bool { return start >= fieldMin }
// e.g. month/dom are 1-based: check start >= 1 before building "start-end" strings Try / catch
sched, err := cron.Parse(spec)
if err != nil {
return fmt.Errorf("invalid cron spec %q: %w", spec, err)
} Prevention
- Remember month and day-of-month are 1-based in this library
- Prefer '*' over explicit ranges that touch the field boundary
- Clamp programmatically generated range starts to field bounds
When it happens
Trigger: Calling cron.Parse with a spec where a range's start is below the field minimum: '0-5 0 0 0 1 *' or '0 0 0 0-5 * *' (dom min is 1), '* * * * 0-11 *' is fine but '0 0 0 * 0 *' (month min is 1) fails. Any schedule string like 'X-Y/step' where X < field min.
Common situations: Copy-pasting 0-based values into 1-based fields (month, day-of-month) from programming contexts where month indexes start at 0; hand-editing crontab entries; generating specs programmatically with an off-by-one loop starting at 0.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- end of range ( ) above maximum ( )
- beginning of range ( ) beyond end of range ( )
- multiple optionals may not be configured
- parser does not accept descriptors
- expected exactly fields, found
AI-assisted analysis of robfig/cron@bc59245fe1 (2026-09-07).
Data as JSON: /api/errors/a79cc2084a9a720c.
Report an issue: GitHub.
Appendix: source
Thrown at parser.go:305
case 2:
step, err = mustParseInt(rangeAndStep[1])
if err != nil {
return 0, err
}
// Special handling: "N/step" means "N-max/step".
if singleDigit {
end = r.max
}
if step > 1 {
extra = 0
}
default:
return 0, fmt.Errorf("too many slashes: %s", expr)
}
if start < r.min {
return 0, fmt.Errorf("beginning of range (%d) below minimum (%d): %s", start, r.min, expr)
}
if end > r.max {
return 0, fmt.Errorf("end of range (%d) above maximum (%d): %s", end, r.max, expr)
}
if start > end {
return 0, fmt.Errorf("beginning of range (%d) beyond end of range (%d): %s", start, end, expr)
}
if step == 0 {
return 0, fmt.Errorf("step of range should be a positive number: %s", expr)
}
return getBits(start, end, step) | extra, nil
}
// parseIntOrName returns the (possibly-named) integer contained in expr.
func parseIntOrName(expr string, names map[string]uint) (uint, error) {
if names != nil {
if namedInt, ok := names[strings.ToLower(expr)]; ok {View on GitHub (pinned to bc59245fe1)