thanos-io/thanos · critical

open block

Error message

open block

What it means

block.Repair wraps the error from tsdb.OpenBlock, which loads the block's index and chunks files into an immutable TSDB block. This fires when the block directory is unreadable, files are missing/corrupt, or meta.json is inconsistent with the on-disk data (e.g. version mismatch). The original tsdb error is wrapped as 'open block: <cause>'.

Solutions

  1. Inspect the wrapped cause: verify the block dir contains meta.json, index, and chunks/ files and that they are not zero-length.
  2. Re-download or re-upload the block from object storage and retry; compare ETag/checksum to detect truncation.
  3. If index is corrupt beyond opening, delete the block and re-upload/re-compact from the source Prometheus.
  4. Check tsdb/Prometheus version compatibility; upgrade Thanos so it can open blocks written by newer Prometheus.

Example fix

// before
if _, err := block.RepairIssue347(ctx, logger, dir, id, source); err != nil {
    return err // opaque 'open block: ...' on truncated block
}
// after
bdir := filepath.Join(dir, id.String())
for _, f := range []string{"meta.json", "index"} {
    if fi, err := os.Stat(filepath.Join(bdir, f)); err != nil || fi.Size() == 0 {
        return fmt.Errorf("block %s missing/empty %s: re-download", id, f)
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

bdir := filepath.Join(dir, id.String())
for _, f := range []string{"meta.json", "index"} {
    if fi, err := os.Stat(filepath.Join(bdir, f)); err != nil || fi.Size() == 0 {
        return fmt.Errorf("block %s: %s missing or empty", id, f)
    }
}
if _, err := metadata.ReadFromDir(bdir); err != nil {
    return err
}

Try / catch

resid, err := block.RepairIssue347(ctx, logger, dir, id, source)
if err != nil && strings.Contains(err.Error(), "open block") {
    // not retryable in place: re-fetch the block, then retry once
    if rerr := redownloadBlock(ctx, bucket, dir, id); rerr != nil {
        return resid, fmt.Errorf("open block failed and re-download failed: %w", rerr)
    }
    resid, err = block.RepairIssue347(ctx, logger, dir, id, source)
}

Prevention

When it happens

Trigger: Repair called on a block dir where chunks/ or index files are missing, truncated, or corrupted (the very corruption Repair is meant to fix can be too severe to open); meta.json missing or invalid; disk I/O or permission errors; tsdb block format version not supported by this binary.

Common situations: Repairing a block pulled from object storage that was truncated during download; running repair after a crashed compaction left partial files; version skew where an older Thanos/tsdb tries to open blocks written by a newer Prometheus; wrong block directory passed (contains no block).

Understand the failure class

Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.

Related errors


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

Appendix: source

Thrown at pkg/block/index.go:434

	if len(ignoreChkFns) == 0 {
		return resid, errors.New("no ignore chunk function specified")
	}

	bdir := filepath.Join(dir, id.String())
	entropy := rand.New(rand.NewSource(time.Now().UnixNano()))
	resid = ulid.MustNew(ulid.Now(), entropy)

	meta, err := metadata.ReadFromDir(bdir)
	if err != nil {
		return resid, errors.Wrap(err, "read meta file")
	}
	if meta.Thanos.Downsample.Resolution > 0 {
		return resid, errors.New("cannot repair downsampled block")
	}

	b, err := tsdb.OpenBlock(logutil.GoKitLogToSlog(logger), bdir, nil, nil)
	if err != nil {
		return resid, errors.Wrap(err, "open block")
	}
	defer runutil.CloseWithErrCapture(&err, b, "repair block reader")

	indexr, err := b.Index()
	if err != nil {
		return resid, errors.Wrap(err, "open index")
	}
	defer runutil.CloseWithErrCapture(&err, indexr, "repair index reader")

	chunkr, err := b.Chunks()
	if err != nil {
		return resid, errors.Wrap(err, "open chunks")
	}
	defer runutil.CloseWithErrCapture(&err, chunkr, "repair chunk reader")

	resdir := filepath.Join(dir, resid.String())

	chunkw, err := chunks.NewWriter(filepath.Join(resdir, ChunksDirname))

View on GitHub (pinned to 35b8b99117)