temporalio/temporal · error
invalid task range, min %v is larger than max %v
Error message
invalid task range, min %v is larger than max %v
What it means
NewRange validates that the inclusive min key does not exceed the exclusive max key, panicking otherwise. A task range must satisfy InclusiveMin <= ExclusiveMax; anything else is a programming error in range construction.
Source
Thrown at service/history/queues/range.go:21
import (
"fmt"
"go.temporal.io/server/service/history/tasks"
)
type (
Range struct {
InclusiveMin tasks.Key
ExclusiveMax tasks.Key
}
)
func NewRange(
inclusiveMin tasks.Key,
exclusiveMax tasks.Key,
) Range {
if inclusiveMin.CompareTo(exclusiveMax) > 0 {
panic(fmt.Sprintf("invalid task range, min %v is larger than max %v", inclusiveMin, exclusiveMax))
}
return Range{
InclusiveMin: inclusiveMin,
ExclusiveMax: exclusiveMax,
}
}
func (r *Range) IsEmpty() bool {
return r.InclusiveMin.CompareTo(r.ExclusiveMax) == 0
}
func (r *Range) ContainsKey(
key tasks.Key,
) bool {
return key.CompareTo(r.InclusiveMin) >= 0 &&
key.CompareTo(r.ExclusiveMax) < 0
}View on GitHub (pinned to bde624efd1)
Solutions
- Validate/swap arguments: if tasks.Key.Compare(min, max) > 0, swap before calling NewRange
- Fix the upstream computation that produced inverted bounds (e.g. Split or time-window logic)
- Use tasks.MinKey/tasks.MaxKey when combining bounds to guarantee ordering
- Add a test asserting the caller's range-building helper for edge-case keys
Example fix
// before
r := tasks.NewRange(loadedMax, loadedMin) // inverted
// after
if loadedMin.CompareTo(loadedMax) > 0 {
loadedMin, loadedMax = loadedMax, loadedMin
}
r := tasks.NewRange(loadedMin, loadedMax) Defensive patterns
Strategy: validation
Validate before calling
if inclusiveMin.CompareTo(exclusiveMax) > 0 {
inclusiveMin, exclusiveMax = exclusiveMax, inclusiveMin
}
r := tasks.NewRange(inclusiveMin, exclusiveMax) Try / catch
func safeNewRange(minKey, maxKey tasks.Key) (r queues.Range) {
defer func() {
if rec := recover(); rec != nil {
r = queues.Range{}
}
}()
return tasks.NewRange(minKey, maxKey)
} Prevention
- Normalize min/max with tasks.MinKey/tasks.MaxKey before constructing
- Double-check time-derived keys for start/end swaps
- Assert ordering in range-building helpers with unit tests
- Never pass user- or config-derived keys unchecked into NewRange
When it happens
Trigger: Calling NewRange with min > max — e.g. computing boundaries in the wrong order, a Split producing inverted halves, or a completed range whose bounds crossed after updates.
Common situations: Negative or zero task IDs skewing key comparison; time-based keys built with start/stop swapped; tests or utilities constructing ranges from user input without ordering.
Related errors
- Unable to split range %v at %v
- Unable to merge range %v with incoming range %v
- Found key with non-zero pending task count but has no corres
- unknown task predicate type: %T
- unknown persistence task predicate type: %v
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/09dc74ebf7ac2cb6.
Report an issue: GitHub.