robfig/cron · error

end of range ( ) above maximum ( )

Error message

end of range (%d) above maximum (%d): %s

What it means

Thrown by getRange in parser.go when the end value of a cron field range exceeds the field's maximum. Each field has fixed bounds (e.g. seconds/minutes 0-59, hours 0-23, day-of-month 1-31, month 1-12, day-of-week 0-6), and getRange rejects ranges whose high end overflows them. This prevents silently wrapping or mis-scheduling values that don't exist in the field.

Solutions

  1. Check the 'above maximum (%d)' value in the error and reduce the range end to the field's ceiling (seconds/minutes 59, hours 23, dom 31, month 12, dow 6)
  2. Use '7' for Sunday? This library's dow is 0-6, so map 7 to 0
  3. Validate spec strings from config/user input with cron.Parse at startup so bad values fail fast
  4. Use '*' for the whole field instead of an explicit max range

Example fix

// before
cron.Parse("0 0 0 * 1-12,13 *") // month max is 12
// after
cron.Parse("0 0 0 * 1-12 *")
Defensive patterns

Strategy: validation

Validate before calling

var fieldMax = map[string]int{"second":59,"minute":59,"hour":23,"dom":31,"month":12,"dow":6}
func validRangeEnd(end int, field string) bool { return end <= fieldMax[field] }

Try / catch

sched, err := cron.Parse(spec)
if err != nil {
	return fmt.Errorf("invalid cron spec %q: %w", spec, err)
}

Prevention

When it happens

Trigger: Calling cron.Parse with a spec like '0 60 * * * *' (minute max 59), '0 0 24 * * *' (hour max 23), '0 0 0 1-32 * *' (dom max 31), '0 0 0 * 1-13 *' (month max 12), or '* * * * * 7-8' under standard dow bounds (max 6).

Common situations: Mistaking hours for a 0-24 range (some systems use 1-24); copying Quartz-style 7-for-Sunday dow values into this library where dow maxes at 6; template strings with placeholders replaced by unvalidated config values.

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


AI-assisted analysis of robfig/cron@bc59245fe1 (2026-09-07). Data as JSON: /api/errors/4ba5e85168d2a6c7. Report an issue: GitHub.

Appendix: source

Thrown at parser.go:308

			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 {
			return namedInt, nil
		}
	}

View on GitHub (pinned to bc59245fe1)