temporalio/temporal · error
errInvalidWorkflowRunTimeoutSeconds
errInvalidWorkflowRunTimeoutSeconds
Error message
%w cause: %v
What it means
Same validation pattern as the execution timeout, applied to WorkflowRunTimeout: timestamp.ValidateAndCapProtoDuration rejects invalid values and the validator wraps the cause with errInvalidWorkflowRunTimeoutSeconds. Run timeouts must be valid, positive, whole-second durations within the server cap.
Source
Thrown at chasm/lib/workflow/validator.go:77
}
return nil
}
type StartWorkflowTimeoutLikeRequest interface {
GetWorkflowExecutionTimeout() *durationpb.Duration
GetWorkflowRunTimeout() *durationpb.Duration
GetWorkflowTaskTimeout() *durationpb.Duration
}
func (v *RequestValidator) ValidateWorkflowTimeouts(
request StartWorkflowTimeoutLikeRequest,
) error {
if err := timestamp.ValidateAndCapProtoDuration(request.GetWorkflowExecutionTimeout()); err != nil {
return fmt.Errorf("%w cause: %v", errInvalidWorkflowExecutionTimeoutSeconds, err)
}
if err := timestamp.ValidateAndCapProtoDuration(request.GetWorkflowRunTimeout()); err != nil {
return fmt.Errorf("%w cause: %v", errInvalidWorkflowRunTimeoutSeconds, err)
}
if err := timestamp.ValidateAndCapProtoDuration(request.GetWorkflowTaskTimeout()); err != nil {
return fmt.Errorf("%w cause: %v", errInvalidWorkflowTaskTimeoutSeconds, err)
}
return nil
}
func (v *RequestValidator) ValidateRetryPolicy(namespaceName string, retryPolicy *commonpb.RetryPolicy) error {
if retryPolicy == nil {
// By default, if the user does not explicitly set a retry policy for a Workflow, do not perform any retries.
return nil
}
retrypolicy.EnsureDefaults(retryPolicy, v.config.defaultWorkflowRetrySettings(namespaceName))
return retrypolicy.Validate(retryPolicy)
}View on GitHub (pinned to bde624efd1)
Solutions
- Set WorkflowRunTimeout to a positive whole-seconds duration within the cap, or leave it unset to inherit execution timeout
- Audit client duration math to avoid sub-second or negative values
- Verify server-side timeout cap dynamic config; raise it or lower the requested value
Example fix
// before req.WorkflowRunTimeout = durationpb.New(1500 * time.Millisecond) // after req.WorkflowRunTimeout = durationpb.New(2 * time.Second)
Defensive patterns
Strategy: validation
Validate before calling
func validRunTimeout(d *durationpb.Duration) bool {
if d == nil { return true }
dur := d.AsDuration()
return dur > 0 && dur%time.Second == 0
}
// call before StartWorkflowExecution / SignalWithStart:
if !validRunTimeout(req.WorkflowRunTimeout) { /* fix or clear field */ } Try / catch
// Go
if err := validator.ValidateWorkflowTimeouts(req); err != nil {
if errors.Is(err, errInvalidWorkflowRunTimeoutSeconds) {
return status.Errorf(codes.InvalidArgument, "run timeout: %v", err)
}
return err
} Prevention
- Round run timeouts up to whole seconds
- Ensure run timeout <= execution timeout and both within caps
- Avoid millisecond-derived durations in request construction
- Leave run timeout unset to inherit execution timeout
When it happens
Trigger: Calling StartWorkflowExecution or SignalWithStart (through ValidateSignalWithStartRequest) with request.WorkflowRunTimeout negative, sub-second, or exceeding the configured maximum.
Common situations: Passing a time.Duration computed from milliseconds (e.g. 1500ms) which fails the whole-seconds validation; negative values from clock/deadline math bugs; exceeding operator-configured timeout caps after a server config change.
Related errors
- errInvalidWorkflowExecutionTimeoutSeconds
- errInvalidWorkflowTaskTimeoutSeconds
- ErrDuplicateRegistration
- name %s is invalid. name must follow golang identifier rules
- error validating ContinueAsNewWorkflowExecutionCommand TaskQ
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/1adadb021f20ce62.
Report an issue: GitHub.