temporalio/temporal · error

errInvalidWorkflowTaskTimeoutSeconds

errInvalidWorkflowTaskTimeoutSeconds

Error message

%w cause: %v

What it means

Same validation pattern applied to WorkflowTaskTimeout: invalid (negative, sub-second, or over-cap) task timeout durations are wrapped with errInvalidWorkflowTaskTimeoutSeconds. The task timeout governs how long a workflow task may run before timing out.

Source

Thrown at chasm/lib/workflow/validator.go:81

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)
}

func (v *RequestValidator) ValidateWorkflowStartDelay(
	cronSchedule string,
	startDelay *durationpb.Duration,

View on GitHub (pinned to bde624efd1)

Solutions

  1. Set WorkflowTaskTimeout to a positive whole-seconds duration within the server cap (e.g. 10s), or leave unset for the default
  2. Use heartbeating/continued tasks instead of raising the task timeout beyond the cap
  3. Fix any duration arithmetic producing fractional or negative values
  4. Check the server's maximum task timeout configuration and match client requests to it

Example fix

// before
req.WorkflowTaskTimeout = durationpb.New(30 * time.Minute)
// after
req.WorkflowTaskTimeout = durationpb.New(10 * time.Second)
Defensive patterns

Strategy: validation

Validate before calling

func validTaskTimeout(d *durationpb.Duration) bool {
    if d == nil { return true }
    dur := d.AsDuration()
    return dur > 0 && dur%time.Second == 0 && dur <= maxAllowedTaskTimeout
}
// call before StartWorkflowExecution / SignalWithStart:
if !validTaskTimeout(req.WorkflowTaskTimeout) { /* fix or clear field */ }

Try / catch

// Go
if err := validator.ValidateWorkflowTimeouts(req); err != nil {
    if errors.Is(err, errInvalidWorkflowTaskTimeoutSeconds) {
        return status.Errorf(codes.InvalidArgument, "task timeout: %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling StartWorkflowExecution or SignalWithStart (through ValidateSignalWithStartRequest) with request.WorkflowTaskTimeout negative, sub-second, or exceeding the maximum allowed task timeout.

Common situations: Clients defaulting task timeout to something like 10s500ms; typo producing a negative duration; requesting a task timeout larger than the server cap (common when trying to allow long-running handlers instead of using heartbeating).

Related errors


AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01). Data as JSON: /api/errors/5f8d857277ac0adf. Report an issue: GitHub.