robfig/cron · error
beginning of range ( ) beyond end of range ( )
Error message
beginning of range (%d) beyond end of range (%d): %s
What it means
Thrown by getRange in parser.go when a cron field range has start > end (e.g. '50-10'). The parser only accepts ascending ranges; it does not wrap around field boundaries like some cron implementations (e.g. Vixie cron's '23-2' hours). If you need wrap-around behavior, express it as two ascending ranges joined with commas.
Solutions
- Split the wrapping range into two ascending comma-separated ranges: '22-6' becomes '22-23,0-6'
- Reorder the range so start <= end if that matches the intent
- Use a step range with '*' plus a filter if the schedule logic needs wrap-around
- Handle the wrap in application logic (e.g. two schedules) rather than one spec string
Example fix
// before
cron.Parse("0 0 22-6 * * *") // wrap-around not supported
// after
cron.Parse("0 0 0-6,22-23 * * *") Defensive patterns
Strategy: validation
Validate before calling
func validAscendingRange(start, end int) bool { return start <= end }
// for wrap-around windows, split: [start,max]+[min,end] Try / catch
sched, err := cron.Parse(spec)
if err != nil {
return fmt.Errorf("invalid cron spec %q: %w", spec, err)
} Prevention
- Never rely on cron range wrap-around; split '22-6' into '22-23,0-6'
- Check start <= end when building ranges from variables
- Document wrap-around windows as two comma-separated ranges in code review checklists
When it happens
Trigger: Calling cron.Parse with a wrapping range: '0 50-10 * * * *' (minutes 50→10), '0 0 23-2 * * *' (hours wrapping midnight), '0 0 0 * 11-2 *' (months Nov→Feb wrapping the year).
Common situations: Assuming cron wrap-around semantics like Unix crontab; describing a recurring overnight window (22:00–06:00) as '22-6'; writing month ranges that cross December.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- beginning of range ( ) below minimum ( )
- end of range ( ) above maximum ( )
- 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/01e518818c86b812.
Report an issue: GitHub.
Appendix: source
Thrown at parser.go:311
// 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 {
return namedInt, nil
}
}
return mustParseInt(expr)
}
View on GitHub (pinned to bc59245fe1)