temporalio/temporal · error

invalid timeout type

Error message

invalid timeout type

What it means

timerTypeToTimerMask in service/history/workflow/timer_sequence.go converts a TimeoutType (SCHEDULE_TO_START, SCHEDULE_TO_CLOSE, START_TO_CLOSE, HEARTBEAT) into a TimerTaskStatus bit. The default branch panics with "invalid timeout type" when given a timeout type without a mapping — notably TIME_OUT_TYPE_UNSPECIFIED or any newer enum value. Raised inside timerTypeToTimerMask, called by CreateNextActivityTimer and TestConversion, when an activity timer is created for an activity whose TimeoutType field is unset or unrecognized.

Source

Thrown at service/history/workflow/timer_sequence.go:460

		Attempt:      activityInfo.Attempt,
	}, true
}

func timerTypeToTimerMask(
	timerType enumspb.TimeoutType,
) int32 {

	switch timerType {
	case enumspb.TIMEOUT_TYPE_START_TO_CLOSE:
		return TimerTaskStatusCreatedStartToClose
	case enumspb.TIMEOUT_TYPE_SCHEDULE_TO_START:
		return TimerTaskStatusCreatedScheduleToStart
	case enumspb.TIMEOUT_TYPE_SCHEDULE_TO_CLOSE:
		return TimerTaskStatusCreatedScheduleToClose
	case enumspb.TIMEOUT_TYPE_HEARTBEAT:
		return TimerTaskStatusCreatedHeartbeat
	default:
		panic("invalid timeout type")
	}
}

// Len implements sort.Interface
func (s TimerSequenceIDs) Len() int {
	return len(s)
}

// Swap implements sort.Interface.
func (s TimerSequenceIDs) Swap(
	this int,
	that int,
) {
	s[this], s[that] = s[that], s[this]
}

// Less implements sort.Interface
func (s TimerSequenceIDs) Less(

View on GitHub (pinned to bde624efd1)

Solutions

  1. Upgrade the server binary so all proto TIMEOUT_TYPE values are recognized (fix version skew).
  2. Inspect the activity's scheduled event / persisted TimeoutType and repair the workflow or reset it to a point before the corrupted activity.
  3. Ensure the SDK/caller sets an explicit timeout type when scheduling activities (never rely on the UNSPECIFIED zero value).
  4. Report with the workflow/activity IDs if it occurs on consistent versions.

Example fix

// before (server-side mapping)
case enumspb.TIMEOUT_TYPE_HEARTBEAT:
    return TimerTaskStatusCreatedHeartbeat
default:
    panic("invalid timeout type")
// after (hardened mapping)
case enumspb.TIMEOUT_TYPE_HEARTBEAT:
    return TimerTaskStatusCreatedHeartbeat
case enumspb.TIMEOUT_TYPE_UNSPECIFIED:
    ms.logger.Warn("activity with unspecified timeout type", ...)
    return TimerTaskStatusCreatedScheduleToClose
Defensive patterns

Strategy: validation

Validate before calling

// Application side: always set explicit timeout types when scheduling activities:
activityOptions := workflow.ActivityOptions{
    ScheduleToStartTimeout: 10 * time.Second,
    StartToCloseTimeout:    30 * time.Second,
    // Set every timeout you use explicitly; never leave TimeoutType unset.
}

Type guard

func hasValidTimeoutType(t enumspb.TimeoutType) bool {
    switch t {
    case enumspb.TIMEOUT_TYPE_SCHEDULE_TO_START,
        enumspb.TIMEOUT_TYPE_SCHEDULE_TO_CLOSE,
        enumspb.TIMEOUT_TYPE_START_TO_CLOSE,
        enumspb.TIMEOUT_TYPE_HEARTBEAT:
        return true
    }
    return false // includes TIMEOUT_TYPE_UNSPECIFIED and newer values
}

Try / catch

// The panic happens inside the history service, not the SDK caller; recover via
// workflow reset rather than catch:
// temporal --ns <ns> workflow reset --wid <wid> --eid <event-id> --reason "corrupt activity timeout"

Prevention

When it happens

Trigger: CreateNextActivityTimer processing an activity whose persisted TimeoutType is TIME_OUT_TYPE_UNSPECIFIED (zero value) or a TIMEOUT_TYPE added in a newer proto/API version than the running server knows.

Common situations: Persistence/API rows written by a newer server with a new TimeoutType then loaded by an older binary; corrupted activity rows where the scheduled event lost its timeout configuration; version-skewed clusters during upgrades.

Understand the failure class

Related errors


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