{"record":{"id":"8cd25346db4ba2fe","repo":"temporalio/temporal","slug":"interval-is-too-small","errorCode":null,"errorMessage":"interval is too small","messagePattern":"interval is too small","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"service/worker/scheduler/spec.go","lineNumber":263,"sourceCode":"\tif len(scs.Comment) > maxCommentLen {\n\t\terrs = append(errs, \"comment is too long\")\n\t}\n\n\tif len(errs) > 0 {\n\t\treturn errors.New(\"invalid calendar spec: \" + strings.Join(errs, \", \"))\n\t}\n\treturn nil\n}\n\nfunc validateInterval(i *schedulepb.IntervalSpec) error {\n\tif i == nil {\n\t\treturn errors.New(\"interval is nil\")\n\t}\n\t// TODO: use timestamp.ValidateAndCapProtoDuration after switching to state machine based implementation.\n\t// \tNot adding it to workflow based implementation to avoid potential non-determinism errors.\n\tiv, phase := timestamp.DurationValue(i.Interval), timestamp.DurationValue(i.Phase)\n\tif iv < time.Second {\n\t\treturn errors.New(\"interval is too small\")\n\t} else if phase < 0 {\n\t\treturn errors.New(\"phase is negative\")\n\t} else if phase >= iv {\n\t\treturn errors.New(\"phase cannot be greater than Interval\")\n\t}\n\treturn nil\n}\n\nfunc (b *SpecBuilder) loadTimezone(spec *schedulepb.ScheduleSpec) (*time.Location, error) {\n\tif spec.TimezoneData != nil {\n\t\treturn time.LoadLocationFromTZData(spec.TimezoneName, spec.TimezoneData)\n\t}\n\n\tif cached, ok := b.locationCache.Get(spec.TimezoneName).(*locationAndError); ok {\n\t\treturn cached.loc, cached.err\n\t}\n\tloc, err := time.LoadLocation(spec.TimezoneName)\n\tb.locationCache.Put(spec.TimezoneName, &locationAndError{","sourceCodeStart":245,"sourceCodeEnd":281,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/service/worker/scheduler/spec.go#L245-L281","documentation":"validateInterval requires the interval duration to be at least one second. Intervals below 1s would make the scheduler fire at sub-second frequency, which the schedule implementation does not support (and the TODO notes validation/capping is deliberately kept out of the workflow-based path to avoid non-determinism).","triggerScenarios":"Submitting an IntervalSpec whose Interval duration is 0 or between 0 and 1 second (e.g. durationpb.New(500*time.Millisecond) or a zero-value durationpb), reached via canonicalizeSpec.","commonSituations":"Confusing Temporal worker poll/pollInterval style sub-second settings with schedule intervals; unit tests with millisecond intervals that pass in workflows but are rejected for schedules; a client sending seconds where milliseconds were intended (or vice versa) producing tiny values.","solutions":["Set the interval to at least 1 second, e.g. durationpb.New(5*time.Second).","Use a worker-side timer/loop for sub-second periodicity instead of a Schedule.","Check unit conversions in the code that builds the duration (ms vs s) before sending the update.","Pre-validate the duration client-side and reject values < time.Second with a clear user-facing message."],"exampleFix":"// before\niv := &schedulepb.IntervalSpec{Interval: durationpb.New(500 * time.Millisecond)}\n// after\niv := &schedulepb.IntervalSpec{Interval: durationpb.New(5 * time.Second)}","handlingStrategy":"validation","validationCode":"d := iv.GetInterval().AsDuration()\nif d < time.Second {\n    return fmt.Errorf(\"schedule interval %s below 1s minimum; use >= 1s\", d)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Remember schedules support a minimum interval of 1 second","Do not confuse worker poll intervals (sub-second) with schedule intervals","Audit duration unit conversions (ms/s) in spec-building code","Use worker-side timers/loops for sub-second periodicity instead of Schedules"],"tags":["go","scheduler","validation","interval"],"backgroundTag":"interval-too-small","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}