{"record":{"id":"98c0cf6f2d50f0b6","repo":"nats-io/nats-server","slug":"end-of-range-d-above-maximum-d-s","errorCode":null,"errorMessage":"end of range (%d) above maximum (%d): %s","messagePattern":"end of range \\((.+?)\\) above maximum \\((.+?)\\): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/cron.go","lineNumber":225,"sourceCode":"\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t\t// Special handling: \"N/step\" means \"N-max/step\".\n\t\tif singleDigit {\n\t\t\tend = r.max\n\t\t}\n\t\tif step > 1 {\n\t\t\textra = 0\n\t\t}\n\tdefault:\n\t\treturn 0, fmt.Errorf(\"too many slashes: %s\", expr)\n\t}\n\n\tif start < r.min {\n\t\treturn 0, fmt.Errorf(\"beginning of range (%d) below minimum (%d): %s\", start, r.min, expr)\n\t}\n\tif end > r.max {\n\t\treturn 0, fmt.Errorf(\"end of range (%d) above maximum (%d): %s\", end, r.max, expr)\n\t}\n\tif start > end {\n\t\treturn 0, fmt.Errorf(\"beginning of range (%d) beyond end of range (%d): %s\", start, end, expr)\n\t}\n\tif step == 0 {\n\t\treturn 0, fmt.Errorf(\"step of range should be a positive number: %s\", expr)\n\t}\n\treturn getBits(start, end, step) | extra, nil\n}\n\n// parseIntOrName returns the (possibly-named) integer contained in expr.\nfunc parseIntOrName(expr string, names map[string]uint) (uint, error) {\n\tif names != nil {\n\t\tif namedInt, ok := names[strings.ToLower(expr)]; ok {\n\t\t\treturn namedInt, nil\n\t\t}\n\t}\n\treturn mustParseInt(expr)","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/cron.go#L207-L243","documentation":"getRange validates a cron field's range end against the field's maximum (e.g. 59 for minutes/seconds, 23 for hours, 12 for months, 6 for dow). An end above the legal maximum is rejected with the expression included in the message.","triggerScenarios":"A range like minutes \"0-60\", hours \"0-24\", months \"1-13\", or day-of-week \"0-7\" passed through parseCron -> getField -> getRange.","commonSituations":"Assuming hours go to 24 (they go 0-23); assuming day-of-week allows 7 like some cron implementations (max is 6 here); copying Linux crontab quirks into the 6-field parser.","solutions":["Clamp the range end to the field max: minutes/seconds 0-59, hours 0-23, dom 1-31, months 1-12, dow 0-6","Replace '7' in day-of-week with '0' (both mean Sunday in classic cron, but 7 exceeds max here)","Use '*' for the whole valid range"],"exampleFix":"// before (hour field)\n expr := \"9-24\"\n// after\n expr := \"9-23\"","handlingStrategy":"validation","validationCode":"var fieldMaxs = map[int]uint{0: 59, 1: 59, 2: 23, 3: 31, 4: 12, 5: 6} // sec,min,hour,dom,mon,dow\n// check range ends <= fieldMaxs[fieldIdx] before scheduling","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Hours max is 23, day-of-week max is 6 (use 0 for Sunday)","Clamp or reject out-of-bounds values when building schedules programmatically"],"tags":["cron","parsing","range-validation"],"backgroundTag":"invalid-cron-expression","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}