temporalio/temporal · error
unknown task status: %v
Error message
unknown task status: %v
What it means
The scanner's fixed-pool executor panics when a submitted task reports a status value the executor's result switch doesn't recognize. TaskStatus is an internal enum; this panic guards against a new status being added without updating the executor loop.
Source
Thrown at service/worker/scanner/executor/executor.go:137
status := task.Run()
switch status {
case TaskStatusDone:
e.outstanding.Add(-1)
metrics.ExecutorTasksDoneCount.With(e.metricsHandler).Record(1)
case TaskStatusDefer:
if e.runQ.deferredCount() < e.maxDeferred {
e.runQ.addAndDefer(task)
metrics.ExecutorTasksDeferredCount.With(e.metricsHandler).Record(1)
} else {
e.outstanding.Add(-1)
metrics.ExecutorTasksDroppedCount.With(e.metricsHandler).Record(1)
}
case TaskStatusErr:
e.outstanding.Add(-1)
metrics.ExecutorTasksErrCount.With(e.metricsHandler).Record(1)
default:
panic(fmt.Sprintf("unknown task status: %v", status))
}
}
}
func (e *fixedPoolExecutor) alive() bool {
return e.status.Load() == common.DaemonStatusStarted
}
View on GitHub (pinned to bde624efd1)
Solutions
- Add a case for the unexpected status in the executor's result switch
- Ensure all scanner task implementations return only statuses handled by the executor
- Roll back or align task/executor code versions if a partial deploy introduced the new status
Example fix
// before
case TaskStatusErr:
e.outstanding.Add(-1)
metrics.ExecutorTasksErrCount.With(e.metricsHandler).Record(1)
default:
panic(fmt.Sprintf("unknown task status: %v", status))
// after
case TaskStatusErr:
e.outstanding.Add(-1)
metrics.ExecutorTasksErrCount.With(e.metricsHandler).Record(1)
case TaskStatusTimeout: // newly added status
e.outstanding.Add(-1)
metrics.ExecutorTasksErrCount.With(e.metricsHandler).Record(1)
default:
e.logger.Error("unknown task status", tag.Status(int(status)))
e.outstanding.Add(-1) Defensive patterns
Strategy: type-guard
Type guard
func isHandledStatus(s TaskStatus) bool {
switch s {
case TaskStatusCompleted, TaskStatusErr, TaskStatusPending:
return true
}
return false
} Prevention
- When adding a TaskStatus variant, search for the executor's result switch and update it in the same change
- Add a unit test that exercises every TaskStatus value through the executor
- Avoid partial deploys mixing new task implementations with old executor binaries
When it happens
Trigger: Raised in the worker loop of fixedPoolExecutor (service/worker/scanner/executor/executor.go:137) when a task's result status is not TaskStatusCompleted, TaskStatusErr, or the other handled values — typically after code changes introduce a new TaskStatus variant not wired into the executor.
Common situations: A developer adds a new task status (e.g. a 'skipped' or 'timeout' status) to the scanner tasks but forgets the executor's switch; mixing versions of task implementations with an older executor.
Related errors
- component is not registered to a library
- task is not registered to a library
- unexpected result from transitionhistory.Compare
- failed to encode chasm path on clean tree: %v
- Failed to get HSM operation log: %v
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/c5a7c4e8d02707a1.
Report an issue: GitHub.