temporalio/temporal · error
Can not append slice to existing list of slices, incoming sl
Error message
Can not append slice to existing list of slices, incoming slice range: %v, existing slice range: %v
What it means
ReaderImpl.AppendSlices panics when the first incoming slice starts before the end of the last slice already held by the reader, i.e. the append would make the reader's slice list non-ordered. AppendSlices is meant for strictly new, later task-key ranges; the reader expects its slices to be sorted and non-overlapping at all times. This is a programmer-invariant panic, not a runtime I/O error.
Source
Thrown at service/history/queues/reader.go:287
r.resetNextReadSliceLocked()
r.monitor.SetSliceCount(r.readerID, r.slices.Len())
}
func (r *ReaderImpl) AppendSlices(incomingSlices ...Slice) {
if len(incomingSlices) == 0 {
return
}
validateSlicesOrderedDisjoint(incomingSlices)
r.Lock()
defer r.Unlock()
if back := r.slices.Back(); back != nil {
lastSliceRange := back.Value.(Slice).Scope().Range
firstIncomingRange := incomingSlices[0].Scope().Range
if lastSliceRange.ExclusiveMax.CompareTo(firstIncomingRange.InclusiveMin) > 0 {
panic(fmt.Sprintf(
"Can not append slice to existing list of slices, incoming slice range: %v, existing slice range: %v ",
firstIncomingRange,
lastSliceRange,
))
}
}
for _, incomingSlice := range incomingSlices {
if scope := incomingSlice.Scope(); scope.IsEmpty() {
continue
}
r.slices.PushBack(incomingSlice)
}
r.resetNextReadSliceLocked()
r.monitor.SetSliceCount(r.readerID, r.slices.Len())
}
View on GitHub (pinned to bde624efd1)
Solutions
- Use MergeSlices (which sorts and merges overlapping slices) instead of AppendSlices when ordering is not guaranteed
- Before appending, check the reader's last slice range and confirm incomingSlices[0].Scope().Range.InclusiveMin >= last.ExclusiveMax
- Sort incomingSlices by InclusiveMin and drop/merge any that overlap existing ranges before calling AppendSlices
Example fix
// before reader.AppendSlices(newSlice) // panics: overlaps existing tail // after reader.MergeSlices(newSlice) // sorts and merges, no panic
Defensive patterns
Strategy: validation
Validate before calling
// caller-side check before AppendSlices
func canAppend(r *queues.Reader, incoming []queues.Slice) bool {
if len(incoming) == 0 { return true }
first := incoming[0].Scope().Range
return first.InclusiveMin.CompareTo(lastExclusiveMax(r)) <= 0 // reader's last slice ExclusiveMax
} Prevention
- Prefer MergeSlices whenever slice ordering relative to existing slices is not guaranteed
- Always sort and dedupe overlapping slices before appending
- Track the reader's last slice range and assert monotonic appends in tests
When it happens
Trigger: Calling reader.AppendSlices(s...) when reader's last slice has ExclusiveMax > s[0].InclusiveMin. Happens when a caller computes slices out of order, or calls AppendSlices instead of MergeSlices for ranges that overlap or precede existing slices.
Common situations: Rebuilding slices after a persistence failure and re-appending stale/older ranges; a task-id ordering assumption changing after an upgrade; concurrent producers appending overlapping shard ranges to the same reader.
Related errors
- Found overlapping incoming slices, left slice range: %v, rig
- reader with ID %v already exists
- Unable to split scope with range %v at %v
- Unable to merge scope with range %v with range %v by range
- Unable to merge scope with range %v with range %v by predica
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/53b13cc36fb37552.
Report an issue: GitHub.