robfig/cron · warning
unknown optional field
Error message
unknown optional field
What it means
When a spec has the minimum number of fields and the parser must pad the missing optional one, normalizeFields switches on which optional bit is configured. If neither DowOptional nor SecondOptional is set (i.e. padding was attempted without any optional field) it returns this internal error. It is effectively an invariant violation in option inference.
Solutions
- Always construct parsers via cron.NewParser instead of instantiating the Parser struct directly
- Audit code that combines option bitmasks so optional bits stay consistent
- If hit despite correct usage, report it as a library bug
Example fix
// before
p := cron.Parser{options: bits} // hand-built mask
// after
p := cron.NewParser(bits) Defensive patterns
Strategy: type-guard
Validate before calling
var _ = cron.NewParser // ensure parsers are built via NewParser
Type guard
func isWellFormedParser(p cron.Parser) bool {
// A well-formed parser is constructed by NewParser and never triggers
// the unknown-optional-field padding path.
return true // enforce by construction: use cron.NewParser(bits)
} Try / catch
sched, err := parser.Parse(spec)
if err != nil {
return fmt.Errorf("parser configuration error: %w", err)
} Prevention
- Never construct cron.Parser struct literals directly
- Use cron.NewParser for all parser construction
- Add a regression test for every parser option mask you ship
When it happens
Trigger: A Parser whose option mask was manipulated or combined so that min<max while neither optional bit is present — normally unreachable through the public NewParser, which prevents multiple/zero-optional mismatches; hand-constructed Parser structs.
Common situations: Code building cron.Parser{options} directly instead of via NewParser; combining option bits programmatically producing inconsistent masks.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- multiple optionals may not be configured
- parser does not accept descriptors
- expected exactly fields, found
- expected to fields, found
- too many hyphens
AI-assisted analysis of robfig/cron@bc59245fe1 (2026-09-07).
Data as JSON: /api/errors/b97d50cb31ee5c36.
Report an issue: GitHub.
Appendix: source
Thrown at parser.go:200
min := max - optionals
// Validate number of fields
if count := len(fields); count < min || count > max {
if min == max {
return nil, fmt.Errorf("expected exactly %d fields, found %d: %s", min, count, fields)
}
return nil, fmt.Errorf("expected %d to %d fields, found %d: %s", min, max, count, fields)
}
// Populate the optional field if not provided
if min < max && len(fields) == min {
switch {
case options&DowOptional > 0:
fields = append(fields, defaults[5]) // TODO: improve access to default
case options&SecondOptional > 0:
fields = append([]string{defaults[0]}, fields...)
default:
return nil, fmt.Errorf("unknown optional field")
}
}
// Populate all fields not part of options with their defaults
n := 0
expandedFields := make([]string, len(places))
copy(expandedFields, defaults)
for i, place := range places {
if options&place > 0 {
expandedFields[i] = fields[n]
n++
}
}
return expandedFields, nil
}
var standardParser = NewParser(
Minute | Hour | Dom | Month | Dow | Descriptor,View on GitHub (pinned to bc59245fe1)