temporalio/temporal · error
interval is not a valid duration: %w
Error message
interval is not a valid duration: %w
What it means
Returned when an interval spec's `interval` duration in a ScheduleSpec fails protobuf timestamp/duration CheckValid() (e.g. nil semantics, negative, or malformed wire data). Temporal validates all interval spec fields server-side before accepting schedule creation/update to prevent undefined scheduler behavior.
Source
Thrown at service/frontend/workflow_handler.go:7016
sizeLimitWarn := wh.config.BlobSizeLimitWarn(namespaceName)
return common.CheckEventBlobSizeLimit(
payloadSize,
sizeLimitWarn,
sizeLimitError,
namespaceName,
scheduleID,
"",
wh.metricsScope(ctx).WithTags(metrics.CommandTypeTag(enumspb.COMMAND_TYPE_UNSPECIFIED.String())),
wh.throttledLogger,
operation,
)
}
func validateScheduleIntervalDurations(spec *schedulepb.ScheduleSpec) error {
for _, interval := range spec.GetInterval() {
if d := interval.GetInterval(); d != nil {
if err := d.CheckValid(); err != nil {
return fmt.Errorf("interval is not a valid duration: %w", err)
}
}
if d := interval.GetPhase(); d != nil {
if err := d.CheckValid(); err != nil {
return fmt.Errorf("phase is not a valid duration: %w", err)
}
}
}
return nil
}
func validateScheduleTimestamps(spec *schedulepb.ScheduleSpec) error {
if err := validateTimestamp(spec.GetStartTime(), "start time"); err != nil {
return err
}
return validateTimestamp(spec.GetEndTime(), "end time")
}
View on GitHub (pinned to bde624efd1)
Solutions
- Ensure each interval duration is > 0 and has consistent seconds/nanoseconds (0 <= nanos < 1e9)
- Use durationpb.New(time.Duration) instead of hand-building durationpb.Duration
- Check for negative or overflowed values when converting from config strings
- Use an SDK typed duration type (e.g. Go time.Duration) so the client serializes correctly
Example fix
// before
interval := &schedulepb.IntervalSpec{Interval: &durationpb.Duration{Seconds: -3600}}
// after
interval := &schedulepb.IntervalSpec{Interval: durationpb.New(1 * time.Hour)} Defensive patterns
Strategy: validation
Validate before calling
func validInterval(d *durationpb.Duration) bool { return d != nil && d.CheckValid() == nil && d.AsDuration() > 0 } Type guard
func isDurationpb(v interface{}) *durationpb.Duration { d, ok := v.(*durationpb.Duration); return d } Try / catch
err := validateScheduleIntervalDurations(spec); if err != nil { return serviceerror.NewInvalidArgumentf(...) } Prevention
- Always build durations with durationpb.New from time.Duration
- Never hand-set Seconds/Nanos fields
- Validate spec client-side before Create/UpdateSchedule
When it happens
Trigger: Calling CreateScheduleAsync or UpdateScheduleAsync (via ValidateScheduleSpec → validateScheduleIntervalDurations) with a ScheduleSpec whose Interval[*].Interval is a zero-value or invalid durationpb.Duration (seconds/nanos inconsistent, negative).
Common situations: Constructing durationpb.Duration manually with wrong sign; decoding corrupted protobuf; deserializing specs from config where seconds/nanos were miscomputed; SDK users passing nil-checked but semantically invalid durations.
Related errors
- phase is not a valid duration: %w
- %s is not a valid timestamp: %w
- %s has unsupported overlap policy %v
- remaining actions cannot be negative
- batchParams is nil
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/51829cfedf7e1f3e.
Report an issue: GitHub.