temporalio/temporal · warning
%s has invalid Step
Error message
%s has invalid Step
What it means
After parsing the step value following a '/', makeRange requires the step to be a positive integer (>= 1). A zero or negative step (e.g. "*/0" or "1-5/-2") yields this error naming the field, since a non-positive step would produce an empty or infinite range.
Source
Thrown at service/worker/scheduler/calendar.go:442
if slashes > 1 {
// Inputs like "3/5/7" should yield the canonical "too many slashes" error
// (instead of a later strconv parse error) so tests get consistent results.
return nil, fmt.Errorf("%s has too many slashes", field)
}
if slashes == 1 {
// A single slash introduces an integer step.
skipParts := strings.SplitN(part, "/", 2)
// Count==1 guarantees len==2; only need to ensure the right side is non-empty.
if skipParts[1] == "" { // e.g. "5/"
return nil, fmt.Errorf("%s missing step value", field)
}
part = skipParts[0]
step, err = strconv.Atoi(skipParts[1])
if err != nil {
return nil, err
}
if step < 1 {
return nil, fmt.Errorf("%s has invalid Step", field)
}
hasStep = true
}
start, end := minVal, maxVal
if part != "*" {
if strings.Contains(part, "-") {
// Only a single dash is allowed to denote a range (e.g. "1-5").
// Inputs with multiple dashes like "1-5-7" should raise the
// canonical "too many dashes" error expected by tests.
if strings.Count(part, "-") > 1 { // no negative numbers are expected in spec
return nil, fmt.Errorf("%s has too many dashes", field)
}
rangeParts := strings.SplitN(part, "-", 2)
if len(rangeParts) != 2 {
return nil, fmt.Errorf("%s has too many dashes", field)
}
if start, err = parseValue(rangeParts[0], minVal, maxVal, parseMode); err != nil {View on GitHub (pinned to bde624efd1)
Solutions
- Use a step >= 1, e.g. "*/0" → "*/1" or "*/5".
- Clamp computed interval values to a minimum of 1 before rendering the spec.
- Validate spec inputs at the application boundary before creating the schedule.
- Review which field the error names to pinpoint the bad part.
Example fix
// before
step := intervalSeconds // could be 0
spec := fmt.Sprintf("*/%d", step)
// after
if step < 1 {
step = 1
}
spec := fmt.Sprintf("*/%d", step) Defensive patterns
Strategy: validation
Validate before calling
step, err := strconv.Atoi(stepPart)
if err != nil || step < 1 {
return errors.New("cron step must be a positive integer")
} Prevention
- Clamp computed intervals to a minimum of 1 before embedding in specs.
- Reject non-positive steps at the config boundary.
- Document that 0 is not a valid cron step in your scheduling docs.
When it happens
Trigger: Submitting a schedule spec field with a step of 0 or negative, like "*/0", "0/0", or "1-5/0"; often the result of arithmetic in generated specs (interval computed as 0).
Common situations: Configuration computed from a duration/interval variable that evaluated to 0; users misremembering cron syntax and using 0 as 'every'; template defaults not initialized.
Related errors
- CronString has time zone but missing fields
- CronString does not have 5-7 fields
- CronString does not have interval after @every
- %s has too many slashes
- %s missing step value
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/e4f48c8bd17940fb.
Report an issue: GitHub.