temporalio/temporal · error
unknown timer task
Error message
unknown timer task
What it means
GetTimerTaskEventID is the timer-task analogue of GetTransferTaskEventID: it maps timer Task implementations (UserTimers, ActivityTimers, WorkflowTaskTimers, WorkflowTimeoutTimers, ActivityTimeoutTimers, ChasmTasks, etc.) to their originating event ID. An unhandled timer task concrete type falls into the default branch and panics with an internal error.
Source
Thrown at service/history/tasks/utils.go:126
eventID = common.FirstEventID
case *DeleteHistoryEventTask:
// Retention task will be used by chasm framework as well,
// and it doesn't depend on any particular state (thus eventID) of the run.
return getChasmTaskEventID()
case *StateMachineTimerTask:
eventID = common.FirstEventID
case *TimeSkippingTimerTask:
// time skipping timer tasks supports both for workflow and chasm executions,
// and it doesn't depend on eventID, so it uses the dummy chasm task eventID here.
return getChasmTaskEventID()
case *ChasmTaskPure:
return getChasmTaskEventID()
case *ChasmTask:
return getChasmTaskEventID()
case *FakeTask:
// no-op
default:
panic(serviceerror.NewInternal("unknown timer task"))
}
return eventID, true
}
View on GitHub (pinned to bde624efd1)
Solutions
- Add a case for the new timer task type returning its event ID (or a sentinel like getChasmTaskEventID equivalent).
- Upgrade all history nodes to a version that recognizes the task type (fix version skew).
- Inspect the task row in persistence to confirm the type is legitimate and not corrupt.
- Add an exhaustiveness unit test covering every timer task implementation in the tasks package.
Example fix
// before
case *ChasmTask:
return getChasmTaskEventID()
default:
panic(serviceerror.NewInternal("unknown timer task"))
// after
case *ChasmTask:
return getChasmTaskEventID()
case *NewTimerTask:
eventID = task.GetTaskID() // or appropriate event source
default:
panic(serviceerror.NewInternal("unknown timer task")) Defensive patterns
Strategy: type-guard
Validate before calling
switch t.(type) {
case *tasks.UserTimerTask, *tasks.ActivityTimeoutTask, *tasks.WorkflowTaskTimeoutTask, *tasks.ChasmTask:
// safe to call
default:
return fmt.Errorf("timer task type %T unsupported", t)
} Type guard
func isKnownTimerTask(t tasks.Task) bool {
switch t.(type) {
case *tasks.UserTimerTask, *tasks.ActivityTimeoutTask,
*tasks.WorkflowTaskTimeoutTask, *tasks.WorkflowTimeoutTask,
*tasks.ActivityTimeoutTask, *tasks.ChasmTask, *tasks.FakeTask:
return true
}
return false
} Prevention
- Update GetTimerTaskEventID whenever a new timer task struct is added
- Upgrade all nodes together; unknown types usually indicate version skew
- Add an exhaustiveness unit test covering every timer task type
- Check persistence rows for unexpected type values before processing
When it happens
Trigger: Passing a timer Task whose concrete type is missing from the type switch into GetTimerTaskEventID — via Tags() when processing timer tasks, usually after a new timer task type was introduced in one version and processed by another.
Common situations: Upgrades where a new timer task type exists in persistence and is loaded by an older binary; fork-specific timer tasks; nil or wrongly-typed tasks placed in the timer queue.
Related errors
- unknown transfer task
- unknown task predicate type: %T
- unsupported deduplication key
- unknown number type: %v
- Found key with non-zero pending task count but has no corres
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/9eee965604ed0a55.
Report an issue: GitHub.