robfig/cron · error
unrecognized descriptor
Error message
unrecognized descriptor: %s
What it means
Thrown by parseDescriptor in parser.go when the schedule string starts with '@' but doesn't match any supported descriptor (@yearly, @annually, @monthly, @weekly, @daily, @midnight, @hourly, or the '@every <duration>' prefix). Parse routes any '@'-prefixed string here first, so unknown at-directives fall through to this error.
Solutions
- Check spelling and case — descriptors are lowercase and exact: @yearly, @annually, @monthly, @weekly, @daily, @midnight, @hourly
- For interval schedules use the exact prefix '@every ' (with a space) followed by a valid duration, e.g. '@every 5m'
- Note '@reboot' is unsupported; register the job explicitly at startup instead
- Validate user-supplied schedule strings with cron.Parse before storing them
Example fix
// before
cron.Parse("@reboot") // not a supported descriptor
// after
cron.Parse("@daily") // or run the job directly in main() Defensive patterns
Strategy: validation
Validate before calling
var descriptors = map[string]bool{"@yearly":true,"@annually":true,"@monthly":true,"@weekly":true,"@daily":true,"@midnight":true,"@hourly":true}
func knownDescriptor(s string) bool {
return descriptors[s] || strings.HasPrefix(s, "@every ")
} Try / catch
sched, err := cron.Parse(spec)
if err != nil {
return fmt.Errorf("invalid cron spec %q: %w", spec, err)
} Prevention
- Descriptors are lowercase and case-sensitive; whitelist them in UI/config validation
- Include the space in '@every <duration>' when building strings dynamically
- Replace unsupported directives like '@reboot' with explicit startup code
When it happens
Trigger: Calling cron.Parse with unsupported or misspelled descriptors: '@every' (missing space), '@ever 5m', '@reboot', '@hourIy' (uppercase I), '@Yearly' (case-sensitive switch), or custom at-syntax like '@interval 10m' that this library doesn't define.
Common situations: Migrating from Vixie cron which supports '@reboot'; copying Quartz or other scheduler directives; typos or capitalization differences; building the descriptor dynamically and forgetting the mandatory space in '@every '; users entering free-form schedule text in a UI.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- multiple optionals may not be configured
- parser does not accept descriptors
- expected exactly fields, found
- expected to fields, found
- unknown optional field
AI-assisted analysis of robfig/cron@bc59245fe1 (2026-09-07).
Data as JSON: /api/errors/6ee065678a2ff352.
Report an issue: GitHub.
Appendix: source
Thrown at parser.go:433
Hour: all(hours),
Dom: all(dom),
Month: all(months),
Dow: all(dow),
Location: loc,
}, nil
}
const every = "@every "
if strings.HasPrefix(descriptor, every) {
duration, err := time.ParseDuration(descriptor[len(every):])
if err != nil {
return nil, fmt.Errorf("failed to parse duration %s: %s", descriptor, err)
}
return Every(duration), nil
}
return nil, fmt.Errorf("unrecognized descriptor: %s", descriptor)
}
View on GitHub (pinned to bc59245fe1)