temporalio/temporal · error
Key encountered positive overflow
Error message
Key encountered positive overflow
What it means
Key.Next computes the lexicographic successor of a task key. When TaskID is MaxInt64 it rolls forward to the next nanosecond with TaskID 0; if FireTime is also at math.MaxInt64 nanoseconds there is no successor and it panics to prevent int64 positive overflow. Called from paths like GetAndCompleteHistoryTask when advancing task keys.
Source
Thrown at service/history/tasks/key.go:84
return 1
}
return 0
}
func (k Key) Prev() Key {
if k.TaskID == 0 {
if k.FireTime.UnixNano() == 0 {
panic("Key encountered negative underflow")
}
return NewKey(k.FireTime.Add(-time.Nanosecond), math.MaxInt64)
}
return NewKey(k.FireTime, k.TaskID-1)
}
func (k Key) Next() Key {
if k.TaskID == math.MaxInt64 {
if k.FireTime.UnixNano() == math.MaxInt64 {
panic("Key encountered positive overflow")
}
return NewKey(k.FireTime.Add(time.Nanosecond), 0)
}
return NewKey(k.FireTime, k.TaskID+1)
}
func (k Key) Sub(subtrahend Key) Key {
borrow := int64(0)
differenceTaskID := k.TaskID - subtrahend.TaskID
if differenceTaskID < 0 {
borrow = 1
differenceTaskID += MaximumKey.TaskID
}
fireTime := k.FireTime.UnixNano() - borrow
subtrahendFireTime := subtrahend.FireTime.UnixNano()
if fireTime < subtrahendFireTime {
panic(fmt.Sprintf("Task key Sub encountered underflow: self: %v, subtrahend: %v", k, subtrahend))View on GitHub (pinned to bde624efd1)
Solutions
- Inspect the offending task's FireTime in persistence; fix the corrupt row or delete/complete it manually.
- Guard the caller: check the key against MaximumKey before calling Next().
- Trace where the max timestamp was written (often a zero-time or clock misconfiguration serialized as max) and fix the writer.
- Add validation when loading tasks so keys near MaximumKey are rejected or repaired at read time.
Example fix
// before
nextKey := task.GetKey().Next()
// after
var nextKey tasks.Key
if task.GetKey() == tasks.MaximumKey {
return serviceerror.NewInternal("task key at maximum, cannot advance")
}
nextKey = task.GetKey().Next() Defensive patterns
Strategy: validation
Validate before calling
if k.CompareTo(tasks.MaximumKey) >= 0 {
return errors.New("task key at maximum, cannot advance")
} Prevention
- Compare against tasks.MaximumKey before calling Next()
- Validate FireTime of tasks loaded from persistence (reject near-max timestamps)
- Investigate any task row whose FireTime looks like a sentinel/corrupt timestamp
When it happens
Trigger: Calling Key.Next() on the maximal key NewKey(time.Unix(0, math.MaxInt64).UTC(), math.MaxInt64); realistically when a task fetched from persistence carries a corrupt/overflowing FireTime and the completion path advances past it.
Common situations: Corrupted persistence rows with sentinel max timestamps; clock/date bugs writing near-max nanosecond timestamps; tests probing boundary keys; retry loops repeatedly calling Next on the same malformed key.
Related errors
- Key encountered negative underflow
- Task key Sub encountered underflow: self: %v, subtrahend: %v
- Unknown category type: %v
- Found key with non-zero pending task count but has no corres
- unknown task predicate type: %T
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/9ee0635ede0049b2.
Report an issue: GitHub.