temporalio/temporal · critical
Unknown category type: %v
Error message
Unknown category type: %v
What it means
peekTaskKey computes the next task Key for a category without consuming an ID. It only supports categories of type Immediate and Scheduled; any other CategoryType (e.g. CategoryTypePosterior or a newly added type not yet wired into the key generator) hits the default branch and panics. This is a developer-invariant panic: the category registry accepted the category but the key generator does not know how to key it.
Source
Thrown at service/history/shard/task_key_generator.go:126
}
}
return nil
}
func (a *taskKeyGenerator) peekTaskKey(
category tasks.Category,
) tasks.Key {
switch category.Type() {
case tasks.CategoryTypeImmediate:
return tasks.NewImmediateKey(a.nextTaskID)
case tasks.CategoryTypeScheduled:
return tasks.NewKey(
a.taskMinScheduledTime,
a.nextTaskID,
)
default:
panic(fmt.Sprintf("Unknown category type: %v", category.Type()))
}
}
func (a *taskKeyGenerator) generateTaskKey(
category tasks.Category,
) (tasks.Key, error) {
id, err := a.generateTaskID()
if err != nil {
return tasks.Key{}, err
}
switch category.Type() {
case tasks.CategoryTypeImmediate:
return tasks.NewImmediateKey(id), nil
case tasks.CategoryTypeScheduled:
return tasks.NewKey(
a.taskMinScheduledTime,
id,View on GitHub (pinned to bde624efd1)
Solutions
- Add a switch case in peekTaskKey for the new category type and return an appropriate tasks.Key.
- Confirm the correct CategoryType was registered for the category in the task category registry (Immediate vs Scheduled).
- If the category should not generate keys through this path, refactor the caller to bypass peekTaskKey for that category.
- Search the tasks package for the category definition and ensure its Type() is one supported by the shard's key generator.
Example fix
// before
default:
panic(fmt.Sprintf("Unknown category type: %v", category.Type()))
// after
case tasks.CategoryTypePosterior:
return tasks.NewKey(a.taskMinScheduledTime, a.nextTaskID)
default:
panic(fmt.Sprintf("Unknown category type: %v", category.Type())) Defensive patterns
Strategy: type-guard
Validate before calling
ct := category.Type()
if ct != tasks.CategoryTypeImmediate && ct != tasks.CategoryTypeScheduled {
return fmt.Errorf("unsupported category type: %v", ct)
} Type guard
func keyableCategory(c tasks.Category) bool {
t := c.Type()
return t == tasks.CategoryTypeImmediate || t == tasks.CategoryTypeScheduled
} Prevention
- When adding a task category, extend both peekTaskKey and generateTaskKey in the same PR
- Add a table-driven test iterating every registered category against the key generator
- Prefer explicit CategoryType at registration and document which types the generator supports
When it happens
Trigger: Calling taskKeyGenerator.peekTaskKey(category) with a tasks.Category whose Type() is not CategoryTypeImmediate or CategoryTypeScheduled — usually when adding a new task category in the tasks package without extending peekTaskKey.
Common situations: Contributors adding a new task category (e.g. a new priority or posterior category) but forgetting to add a switch case; custom forks introducing category types not present upstream.
Related errors
- Found key with non-zero pending task count but has no corres
- Key encountered negative underflow
- Key encountered positive overflow
- Task key Sub encountered underflow: self: %v, subtrahend: %v
- expect at least one reservation
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/630bf46dc9dd327d.
Report an issue: GitHub.