{"record":{"id":"c71846b0f5f27b07","repo":"thanos-io/thanos","slug":"close","errorCode":null,"errorMessage":"close","messagePattern":"close","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/compactv2/compactor.go","lineNumber":89,"sourceCode":"\ts := New(tmpDir, logger, changeLogger, pool)\n\ts.dryRun = true\n\treturn s\n}\n\n// TODO(bwplotka): Upstream this.\nfunc (w *Compactor) WriteSeries(ctx context.Context, readers []block.Reader, sWriter block.Writer, p ProgressLogger, modifiers ...Modifier) (err error) {\n\tif len(readers) == 0 {\n\t\treturn errors.New(\"cannot write from no readers\")\n\t}\n\n\tvar (\n\t\tsReaders []seriesReader\n\t\tclosers  []io.Closer\n\t)\n\tdefer func() {\n\t\terrs := tsdb_errors.NewMulti(err)\n\t\tif cerr := tsdb_errors.CloseAll(closers); cerr != nil {\n\t\t\terrs.Add(errors.Wrap(cerr, \"close\"))\n\t\t}\n\t\terr = errs.Err()\n\t}()\n\n\tfor _, b := range readers {\n\t\tindexr, err := b.Index()\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"open index reader for block %+v\", b.Meta())\n\t\t}\n\t\tclosers = append(closers, indexr)\n\n\t\tchunkr, err := b.Chunks()\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"open chunk reader for block %+v\", b.Meta())\n\t\t}\n\t\tclosers = append(closers, chunkr)\n\t\tsReaders = append(sReaders, seriesReader{ir: indexr, cr: chunkr})\n\t}","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/compactv2/compactor.go#L71-L107","documentation":"When WriteSeries finishes (or panics via defer), it closes all opened block readers with tsdb_errors.CloseAll. If any Close returns an error, it is wrapped with \"close\" and merged into the returned multi-error. This is a cleanup-path failure: the compaction itself may have succeeded but resource release failed.","triggerScenarios":"b.Index() or b.Chunks() returned a reader whose Close fails — e.g. underlying file descriptor already closed, disk I/O error on close, or a custom block.Reader implementation returning an error from Close.","commonSituations":"Disk errors/EIO on unclean storage, double-close bugs in custom block reader implementations, or file-descriptor exhaustion causing close failures on packed block files.","solutions":["Inspect the wrapped inner error to find which reader's Close failed and fix the underlying I/O or double-close cause","Check disk health and file descriptor limits (ulimit) on the node running compaction","If you implement block.Reader/Index/Chunks, make Close idempotent and nil-safe","Retry the compaction after transient I/O errors"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Pre-check block files are readable before compaction\nfor _, b := range readers {\n    if _, err := b.Index(); err != nil { return err }\n    if _, err := b.Chunks(); err != nil { return err }\n}","typeGuard":null,"tryCatchPattern":"if err := comp.WriteSeries(ctx, readers, sWriter, progress); err != nil {\n    if strings.Contains(err.Error(), \"close\") {\n        // cleanup-path failure; log and inspect underlying cause\n        logger.Warn(\"compaction ok but reader close failed\", \"err\", err)\n    }\n    return err\n}","preventionTips":["Implement Close idempotently in custom block readers","Monitor disk health and file-descriptor limits on compaction nodes","Log multi-errors fully so close-path failures are visible"],"tags":["go","resource-cleanup","io"],"backgroundTag":"file-close-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"}