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

  1. Check len(strings.TrimSpace(spec)) > 0 before calling Parse
  2. Provide a default schedule when the spec is empty
  3. 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

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


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)