temporalio/temporal · error

Found overlapping iterators in iterator list, left range: %v

Error message

Found overlapping iterators in iterator list, left range: %v, right range: %v

What it means

validateIteratorsOrderedDisjoint checks a list of task iterators is sorted and non-overlapping before they are merged by mergeIterators. Each iterator covers a [min, max) key range; if an iterator's ExclusiveMax is >= the next iterator's InclusiveMin the ranges overlap and processing would visit keys twice, so the code panics. This is an internal invariant protecting the merge of split iterators.

Source

Thrown at service/history/queues/slice.go:509

	if s.scope.IsEmpty() {
		s.destroy()
		return mergedSlices
	}

	return append(mergedSlices, s)
}

func validateIteratorsOrderedDisjoint(
	iterators []Iterator,
) {
	if len(iterators) <= 1 {
		return
	}

	for idx, iterator := range iterators[:len(iterators)-1] {
		nextIterator := iterators[idx+1]
		if iterator.Range().ExclusiveMax.CompareTo(nextIterator.Range().InclusiveMin) >= 0 {
			panic(fmt.Sprintf(
				"Found overlapping iterators in iterator list, left range: %v, right range: %v",
				iterator.Range(),
				nextIterator.Range(),
			))
		}
	}
}

View on GitHub (pinned to bde624efd1)

Solutions

  1. Ensure iterators passed to mergeIterators are sorted ascending by InclusiveMin with disjoint ranges
  2. Fix range math in the code producing the iterators (SplitByRange must produce strictly ordered disjoint sub-ranges)
  3. Validate custom Iterator.Range() implementations match actual yielded keys
  4. Report to temporalio/temporal with both printed ranges if this occurs on an unmodified build

Example fix

// before: appending split iterators unordered
iterators := append(leftIterators, rightIterators...)
// after: sort by range min before merging
sort.Slice(iterators, func(i, j int) bool {
  return iterators[i].Range().InclusiveMin.CompareTo(iterators[j].Range().InclusiveMin) < 0
})
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check before merging custom iterator lists:
for i := 0; i < len(iterators)-1; i++ {
  if iterators[i].Range().ExclusiveMax.CompareTo(iterators[i+1].Range().InclusiveMin) >= 0 {
    return fmt.Errorf("iterators %d and %d overlap", i, i+1)
  }
}

Try / catch

func safeMerge(iterators []queues.Iterator) (it queues.Iterator, err error) {
  defer func() { if r := recover(); r != nil { err = fmt.Errorf("iterator merge panic: %v", r) } }()
  return queues.MergeIterators(iterators), nil
}

Prevention

When it happens

Trigger: mergeIterators called with iterators assembled out of order or whose ranges overlap — e.g. after a bug in SplitByRange/SplitByPredicate range math, or a custom tasks.Iterator whose Range() disagrees with the keys it actually yields.

Common situations: Only inside temporal-server history queue internals; appears after changes to split logic, upgrade mixing versions, or custom iterator implementations in forks.

Related errors


AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01). Data as JSON: /api/errors/06e793ff2de8c958. Report an issue: GitHub.