{"record":{"id":"53b13cc36fb37552","repo":"temporalio/temporal","slug":"can-not-append-slice-to-existing-list-of-slices-i","errorCode":null,"errorMessage":"Can not append slice to existing list of slices, incoming slice range: %v, existing slice range: %v ","messagePattern":"Can not append slice to existing list of slices, incoming slice range: (.+?), existing slice range: (.+?) ","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"service/history/queues/reader.go","lineNumber":287,"sourceCode":"\tr.resetNextReadSliceLocked()\n\tr.monitor.SetSliceCount(r.readerID, r.slices.Len())\n}\n\nfunc (r *ReaderImpl) AppendSlices(incomingSlices ...Slice) {\n\tif len(incomingSlices) == 0 {\n\t\treturn\n\t}\n\n\tvalidateSlicesOrderedDisjoint(incomingSlices)\n\n\tr.Lock()\n\tdefer r.Unlock()\n\n\tif back := r.slices.Back(); back != nil {\n\t\tlastSliceRange := back.Value.(Slice).Scope().Range\n\t\tfirstIncomingRange := incomingSlices[0].Scope().Range\n\t\tif lastSliceRange.ExclusiveMax.CompareTo(firstIncomingRange.InclusiveMin) > 0 {\n\t\t\tpanic(fmt.Sprintf(\n\t\t\t\t\"Can not append slice to existing list of slices, incoming slice range: %v, existing slice range: %v \",\n\t\t\t\tfirstIncomingRange,\n\t\t\t\tlastSliceRange,\n\t\t\t))\n\t\t}\n\t}\n\n\tfor _, incomingSlice := range incomingSlices {\n\t\tif scope := incomingSlice.Scope(); scope.IsEmpty() {\n\t\t\tcontinue\n\t\t}\n\t\tr.slices.PushBack(incomingSlice)\n\t}\n\n\tr.resetNextReadSliceLocked()\n\tr.monitor.SetSliceCount(r.readerID, r.slices.Len())\n}\n","sourceCodeStart":269,"sourceCodeEnd":305,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/service/history/queues/reader.go#L269-L305","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nreader.AppendSlices(newSlice) // panics: overlaps existing tail\n\n// after\nreader.MergeSlices(newSlice) // sorts and merges, no panic","handlingStrategy":"validation","validationCode":"// caller-side check before AppendSlices\nfunc canAppend(r *queues.Reader, incoming []queues.Slice) bool {\n  if len(incoming) == 0 { return true }\n  first := incoming[0].Scope().Range\n  return first.InclusiveMin.CompareTo(lastExclusiveMax(r)) <= 0 // reader's last slice ExclusiveMax\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["go","history-service","task-queue","slice-ordering","panic"],"backgroundTag":"slice-range-overlap","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}