{"record":{"id":"0d6e03ca69e7297e","repo":"thanos-io/thanos","slug":"add-series-0d6e03","errorCode":null,"errorMessage":"add series","messagePattern":"add series","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/compactv2/chunk_series_set.go","lineNumber":223,"sourceCode":"\t\t\tchks = append(chks, chksIter.At())\n\t\t}\n\n\t\tif chksIter.Err() != nil {\n\t\t\treturn errors.Wrap(chksIter.Err(), \"chunk iter\")\n\t\t}\n\n\t\t// Skip the series with all deleted chunks.\n\t\tif len(chks) == 0 {\n\t\t\t// All series will be ignored.\n\t\t\tp.SeriesProcessed()\n\t\t\tcontinue\n\t\t}\n\n\t\tif err := sWriter.WriteChunks(chks...); err != nil {\n\t\t\treturn errors.Wrap(err, \"write chunks\")\n\t\t}\n\t\tif err := sWriter.AddSeries(ref, s.Labels(), chks...); err != nil {\n\t\t\treturn errors.Wrap(err, \"add series\")\n\t\t}\n\t\tfor _, chk := range chks {\n\t\t\t// ChunkPool is used by tsdb.OpenBlock BlockReader.\n\t\t\tif err := w.chunkPool.Put(chk.Chunk); err != nil {\n\t\t\t\treturn errors.Wrap(err, \"put chunk\")\n\t\t\t}\n\t\t}\n\t\tref++\n\t\tp.SeriesProcessed()\n\t}\n\tif populatedSet.Err() != nil {\n\t\treturn errors.Wrap(populatedSet.Err(), \"iterate populated chunk series set\")\n\t}\n\n\treturn nil\n}\n","sourceCodeStart":205,"sourceCodeEnd":240,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/compactv2/chunk_series_set.go#L205-L240","documentation":"sWriter.AddSeries failed when registering a series (labels + chunk metas) into the destination index after its chunks were written. The index writer validates labelsets and refs; failures here abort the compaction output.","triggerScenarios":"write() calls sWriter.AddSeries(ref, s.Labels(), chks...) after WriteChunks; failure on invalid/duplicate label sets (empty or duplicate series), invalid chunk refs written out of order, or underlying index file IO error.","commonSituations":"Duplicate or out-of-order series in the input stream (unsorted series set bug or deduplication failure), empty labelset series after label removal/external relabeling, index writer invariant violations.","solutions":["Inspect the wrapped cause for 'duplicate' or 'empty labelset'; fix relabeling configs that can strip all labels from series.","Ensure the input series set is sorted and deduplicated before WriteSeries (compactv2 expects sorted input).","Retry compaction with fresh output; check the wrapped error for IO issues (disk full) if not a validation failure.","If triggered by custom code, verify chunk metas were written via WriteChunks before AddSeries with matching refs."],"exampleFix":"// before: empty labelsets slip through relabeling and fail AddSeries\n// after: filter degenerate series before compaction\nif labels.IsEmpty() {\n    p.SeriesProcessed()\n    continue\n}","handlingStrategy":"validation","validationCode":"// reject series that would fail AddSeries before writing\nif labels.IsEmpty() || hasDuplicateSeries(seen, labels) {\n    p.SeriesProcessed()\n    continue\n}","typeGuard":"func isValidSeriesSet(lset labels.Labels) bool {\n    return lset != nil && lset.Len() > 0 && lset.IsValid()\n}","tryCatchPattern":"if err := WriteSeries(ctx, set, symbols); err != nil {\n    if strings.Contains(err.Error(), \"duplicate\") || strings.Contains(err.Error(), \"empty\") {\n        return errors.Wrap(err, \"input series not sorted/deduplicated; check relabel config\")\n    }\n    return err\n}","preventionTips":["Ensure input series sets are sorted and deduplicated before compaction","Audit relabel configs for rules that can strip all labels","Always call WriteChunks before AddSeries for matching refs","Discard partial output and retry with a fresh index writer after failures"],"tags":["go","tsdb","index-writer","labels"],"backgroundTag":"file-write-failed","analyzedSha":"35b8b991177def87ed52dcf10f9b6d87f07282c8","analyzedAt":"2026-09-07T01:49:59.689Z","contentChangedAt":"2026-09-07T01:49:59.689Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}