robfig/cron · error

failed to parse int from

Error message

failed to parse int from %s: %s

What it means

Thrown by mustParseInt in parser.go when a numeric token in a cron field cannot be parsed by strconv.Atoi. Any field component expected to be a plain non-negative integer (or a name like 'mon' when names are defined) that contains non-digit characters or overflows int reaches this error. The original strconv error is embedded in the message.

Solutions

  1. Inspect the token shown after 'failed to parse int from' and correct/remove the non-numeric characters
  2. Trim whitespace/BOM from spec strings read from files or env before parsing
  3. Use the NewParser with built-in name support or write the numeric equivalent instead of month/day names if the parser has no names map
  4. Validate the spec at application startup rather than lazily so bad config fails fast

Example fix

// before
cron.Parse("0 0 {{.hour}} * * *") // placeholder not substituted
// after
spec := fmt.Sprintf("0 0 %d * * *", hour) // hour is a validated int
Defensive patterns

Strategy: validation

Validate before calling

func isNumericToken(s string) bool {
	if s == "" { return false }
	for _, r := range s { if r < '0' || r > '9' { return false } }
	return true
}

Try / catch

sched, err := cron.Parse(spec)
if err != nil {
	return fmt.Errorf("invalid cron spec %q: %w", spec, err)
}

Prevention

When it happens

Trigger: Calling cron.Parse with malformed numeric tokens: 'abc' in a numeric-only field like hours ('0 * abc * * *'), '01.5', '1e3', '99999999999999999999' (overflow), a stray character like '1O' (letter O instead of zero), or a week name like 'mon' in a field with no names map.

Common situations: Typos in hand-written crontab strings; locale characters or invisible whitespace (BOM, non-breaking spaces) inside the spec; template substitution leaving literal placeholders like '{{.minute}}'; copying Quartz names ('JAN', 'SUN') into fields of the default parser where names aren't registered.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of robfig/cron@bc59245fe1 (2026-09-07). Data as JSON: /api/errors/cdd36505d672ac27. Report an issue: GitHub.

Appendix: source

Thrown at parser.go:334

	return getBits(start, end, step) | extra, nil
}

// parseIntOrName returns the (possibly-named) integer contained in expr.
func parseIntOrName(expr string, names map[string]uint) (uint, error) {
	if names != nil {
		if namedInt, ok := names[strings.ToLower(expr)]; ok {
			return namedInt, nil
		}
	}
	return mustParseInt(expr)
}

// mustParseInt parses the given expression as an int or returns an error.
func mustParseInt(expr string) (uint, error) {
	num, err := strconv.Atoi(expr)
	if err != nil {
		return 0, fmt.Errorf("failed to parse int from %s: %s", expr, err)
	}
	if num < 0 {
		return 0, fmt.Errorf("negative number (%d) not allowed: %s", num, expr)
	}

	return uint(num), nil
}

// getBits sets all bits in the range [min, max], modulo the given step size.
func getBits(min, max, step uint) uint64 {
	var bits uint64

	// If step is 1, use shifts.
	if step == 1 {
		return ^(math.MaxUint64 << (max + 1)) & (math.MaxUint64 << min)
	}

	// Else, use a simple loop.

View on GitHub (pinned to bc59245fe1)