robfig/cron · error
empty spec string
Error message
empty spec string
What it means
Parse rejects an empty spec string before doing any parsing. A cron schedule expression must contain at least one field, so an empty input is immediately invalid and returned as an error rather than a schedule.
Solutions
- Check len(strings.TrimSpace(spec)) > 0 before calling Parse
- Provide a default schedule when the spec is empty
- Return a friendlier validation error to the user before invoking Parse
Example fix
// before
sched, err := parser.Parse(cfg.Spec)
// after
if strings.TrimSpace(cfg.Spec) == "" {
return nil, fmt.Errorf("cron spec is required")
}
sched, err := parser.Parse(cfg.Spec) Defensive patterns
Strategy: validation
Validate before calling
if strings.TrimSpace(spec) == "" {
return nil, errors.New("cron spec must not be empty")
} Try / catch
sched, err := parser.Parse(spec)
if err != nil {
return fmt.Errorf("invalid cron spec %q: %w", spec, err)
} Prevention
- Trim and check config/env values before parsing
- Fail fast at config-load time on empty schedules
- Provide sensible default schedules for optional config
When it happens
Trigger: Calling Parser.Parse("") — e.g. spec read from an empty config value, environment variable, or untrimmed whitespace that was stripped to nothing.
Common situations: Config files or env vars where CRON_SPEC= is unset; YAML/JSON config with a blank string value passed straight to Parse; trimming user input down to zero length.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- expected exactly fields, found
- expected to fields, found
- multiple optionals may not be configured
- provided bad location
- parser does not accept descriptors
AI-assisted analysis of robfig/cron@bc59245fe1 (2026-09-07).
Data as JSON: /api/errors/da47bd721da57f6a.
Report an issue: GitHub.
Appendix: source
Thrown at parser.go:90
optionals := 0
if options&DowOptional > 0 {
optionals++
}
if options&SecondOptional > 0 {
optionals++
}
if optionals > 1 {
panic("multiple optionals may not be configured")
}
return Parser{options}
}
// Parse returns a new crontab schedule representing the given spec.
// It returns a descriptive error if the spec is not valid.
// It accepts crontab specs and features configured by NewParser.
func (p Parser) Parse(spec string) (Schedule, error) {
if len(spec) == 0 {
return nil, fmt.Errorf("empty spec string")
}
// Extract timezone if present
var loc = time.Local
if strings.HasPrefix(spec, "TZ=") || strings.HasPrefix(spec, "CRON_TZ=") {
var err error
i := strings.Index(spec, " ")
eq := strings.Index(spec, "=")
if loc, err = time.LoadLocation(spec[eq+1 : i]); err != nil {
return nil, fmt.Errorf("provided bad location %s: %v", spec[eq+1:i], err)
}
spec = strings.TrimSpace(spec[i:])
}
// Handle named schedules (descriptors), if configured
if strings.HasPrefix(spec, "@") {
if p.options&Descriptor == 0 {
return nil, fmt.Errorf("parser does not accept descriptors: %v", spec)View on GitHub (pinned to bc59245fe1)