temporalio/temporal · error
schedule spec next-time search exceeded the compute iteratio
Error message
schedule spec next-time search exceeded the compute iteration limit
What it means
ErrComputeLimitExceeded is returned by GetNextTime when searching for the next schedule spec occurrence (skipping excluded times) exceeds a hard iteration bound configured via warnIterations/maxIterations. It guards against specs (e.g. calendars with many exclusion blocks or extremely tight intervals) that would otherwise consume unbounded CPU in the scheduler workflow.
Source
Thrown at service/worker/scheduler/spec.go:60
// locationCache is a cache for the results of time.LoadLocation. That function accesses
// the filesystem and is relatively slow. We assume that it returns a semantically
// equivalent value for the same location name. This isn't strictly true, for example if
// the time zone database is changed while the process is running. To handle that, we
// expire entries after a day. Note that we cache negative results also.
locationCache cache.Cache
warnIterations dynamicconfig.IntPropertyFn
maxIterations dynamicconfig.IntPropertyFn
}
locationAndError struct {
loc *time.Location
err error
}
)
// ErrComputeLimitExceeded is returned by GetNextTime when the search for the next matching time
// hits the hard compute iteration bound before finding a non-excluded time.
var ErrComputeLimitExceeded = errors.New("schedule spec next-time search exceeded the compute iteration limit")
var ErrScheduleSpecLimitHit = serviceerror.NewInvalidArgument("the schedule calendar specification has too many exclusions. Please modify the specification.")
// NewSpecBuilder takes the compute-limit getters directly (rather than a *dynamicconfig.Collection)
// so the dynamic-config plumbing stays in the wiring layer, per the common codebase pattern.
func NewSpecBuilder(warnIterations, maxIterations dynamicconfig.IntPropertyFn) *SpecBuilder {
return &SpecBuilder{
warnIterations: warnIterations,
maxIterations: maxIterations,
locationCache: cache.New(1000,
&cache.Options{
TTL: 24 * time.Hour,
},
),
}
}
func (b *SpecBuilder) NewCompiledSpec(spec *schedulepb.ScheduleSpec) (*CompiledSpec, error) {
spec, err := canonicalizeSpec(spec)View on GitHub (pinned to bde624efd1)
Solutions
- Simplify the schedule spec: reduce the number of exclusion intervals or replace many calendar entries with fewer broader ones.
- Increase the scheduler spec compute limit dynamic config values (warnIterations / maxIterations) if the spec is legitimate but complex.
- Narrow exclusion windows so the next-time search finds a match faster.
- Reproduce locally with TestGetNextTimeComputeLimitExceeded-style iteration counts to confirm which part of the spec drives the search past the limit.
Example fix
// before maxIterations := dc.GetIntPropertyFn(dynamicconfig.SchedulerSpecComputeMaxIterations) // e.g. 1000, too low for complex spec // after maxIterations := dc.GetIntPropertyFn(dynamicconfig.SchedulerSpecComputeMaxIterations) // raised to 100000 for this namespace // or reduce spec complexity: collapse 50 exclusion ranges into 3
Defensive patterns
Strategy: validation
Validate before calling
// before scheduling, sanity-check spec complexity
if len(spec.ExcludeCalendar)+len(spec.ExcludeTimes) > 100 {
return fmt.Errorf("spec has %d exclusions; risk of compute-limit failure", len(spec.ExcludeCalendar)+len(spec.ExcludeTimes))
} Try / catch
result, err := GetNextTime(...)
if errors.Is(err, scheduler.ErrComputeLimitExceeded) {
// alert: spec too complex; simplify exclusions or raise dynamic config limit
} Prevention
- Keep exclusion lists small and merged into the fewest intervals
- Tune the scheduler spec compute-limit dynamic config per namespace
- Test complex specs with TestGetNextTimeComputeLimitExceeded-style limits before production
- Avoid schedules whose next occurrence falls inside long exclusion windows
When it happens
Trigger: GetNextTime / checkNextScheduleResult is called with a schedule spec whose next matching time cannot be found within maxIterations iterations — typically a calendar spec combined with large exclusion ranges, or an interval spec with a phase that pushes matches far into excluded periods.
Common situations: Schedules built programmatically with many calendar entries and broad ExcludeCalendar lists; timezone/DST edge cases generating long gap searches; misconfigured maxIterations dynamic config set too low for legitimate specs; long blocked periods (maintenance windows) covering many candidate times.
Related errors
- out of range
- conflicting timezone names
- ${errs}
- CronString has time zone but missing fields
- CronString does not have 5-7 fields
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/9decb3f4074f044e.
Report an issue: GitHub.