thanos-io/thanos · warning

close block

Error message

close block

What it means

Wraps b.Close() failure while removing/unloading a block from the BucketStore. The block was found in the loaded map and its metrics decremented, but closing the block's index reader, chunk pool, or temp directory failed. The block directory cleanup is skipped when the block was not downloaded (dir is empty).

Solutions

  1. Check the wrapped root error: if it is a directory-removal failure, verify the cache/temp directory is writable and mounted.
  2. Check for file-descriptor or memory pressure that breaks reader Close paths; raise limits or reduce max concurrency.
  3. Restart the store gateway after the transient condition clears; Close failures are rarely actionable in-process.
Defensive patterns

Strategy: try-catch

Try / catch

if err := store.RemoveBlock(ctx, id); err != nil && strings.Contains(err.Error(), "close block") {
	logger.Warn("non-fatal block close failure, will retry next sync", "err", err)
} else if err != nil {
	return err
}

Prevention

When it happens

Trigger: removeBlock is called during block sync for a block no longer present in the bucket, and BucketBlock.Close returns an error closing the index reader, chunk reader, or on-disk directory.

Common situations: File-descriptor exhaustion preventing readers from closing cleanly, temp-dir on a failing/unmounted disk preventing directory removal, blocks evicted during shutdown while queries still hold readers.

Related errors


AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07). Data as JSON: /api/errors/2ad4d2b3d52e6995. Report an issue: GitHub.

Appendix: source

Thrown at pkg/store/bucket.go:939

}

func (s *BucketStore) removeBlock(id ulid.ULID) error {
	s.mtx.Lock()
	b, ok := s.blocks[id]
	if ok {
		lset := labels.FromMap(b.meta.Thanos.Labels)
		s.blockSets[lset.Hash()].remove(id)
		delete(s.blocks, id)
	}
	s.mtx.Unlock()

	if !ok {
		return nil
	}

	s.metrics.blocksLoaded.Dec()
	if err := b.Close(); err != nil {
		return errors.Wrap(err, "close block")
	}

	if b.dir == "" {
		return nil
	}

	return os.RemoveAll(b.dir)
}

// TimeRange returns the minimum and maximum timestamp of data available in the store.
func (s *BucketStore) TimeRange() (mint, maxt int64) {
	s.mtx.RLock()
	defer s.mtx.RUnlock()

	mint = math.MaxInt64
	maxt = math.MinInt64

	for _, b := range s.blocks {

View on GitHub (pinned to 35b8b99117)