thanos-io/thanos · error

open index writer

Error message

open index writer

What it means

NewDiskWriter fails when index.NewWriter cannot create the index writer for the temporary block's index file. Without an index the block is unusable, so creation aborts right after the chunk writer was opened.

Solutions

  1. Check free disk space — index writing needs headroom after chunks.
  2. Verify write permissions on the block temp directory.
  3. Ensure no leftover file exists at <bTmp>/index blocking the new writer.
  4. Pass a live (non-cancelled) context to NewDiskWriter.

Example fix

// before
d, err := NewDiskWriter(ctx, cancelledCtx, bdir) // ctx already cancelled
// after
d, err := NewDiskWriter(ctx, context.Background(), bdir)
Defensive patterns

Strategy: try-catch

Validate before calling

if err := ctx.Err(); err != nil {
    return fmt.Errorf("context cancelled before block write: %w", err)
}
if free, err := diskFree(bdir); err == nil && free < minRequiredBytes {
    return fmt.Errorf("insufficient disk space: %d bytes free", free)
}

Try / catch

d, err := block.NewDiskWriter(ctx, bdir, logger)
if err != nil {
    if strings.Contains(err.Error(), "open index writer") {
        return fmt.Errorf("cannot create index writer (disk space/ctx?): %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: index.NewWriter(ctx, <bTmp>/index) failing due to OS-level open/creation errors: permission denied, disk full, path conflicts, or invalid context already cancelled.

Common situations: Disk full after chunk writing consumed space; write permissions removed mid-write; a stale regular file at the index path blocking creation; context cancelled before writer setup.

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/72f3b809f00070ee. Report an issue: GitHub.

Appendix: source

Thrown at pkg/block/writer.go:96

	if err = os.RemoveAll(bTmp); err != nil {
		return nil, err
	}
	if err = os.MkdirAll(bTmp, 0750); err != nil {
		return nil, err
	}

	chunkw, err := chunks.NewWriter(filepath.Join(bTmp, ChunksDirname))
	if err != nil {
		return nil, errors.Wrap(err, "open chunk writer")
	}
	d.closers = append(d.closers, chunkw)

	// TODO(bwplotka): Setup instrumentedChunkWriter if we want to upstream this code.

	indexw, err := index.NewWriter(ctx, filepath.Join(bTmp, IndexFilename))
	if err != nil {
		return nil, errors.Wrap(err, "open index writer")
	}
	d.closers = append(d.closers, indexw)
	d.statsGatheringSeriesWriter = statsGatheringSeriesWriter{iw: indexw, cw: chunkw}
	return d, nil
}

func (d *DiskWriter) Flush() (_ tsdb.BlockStats, err error) {
	defer func() {
		if err != nil {
			err = tsdb_errors.NewMulti(err, tsdb_errors.CloseAll(d.closers)).Err()
			if err := os.RemoveAll(d.bTmp); err != nil {
				level.Error(d.logger).Log("msg", "removed tmp folder failed after block(s) write", "err", err.Error())
			}
		}
	}()
	df, err := fileutil.OpenDir(d.bTmp)
	if err != nil {
		return tsdb.BlockStats{}, errors.Wrap(err, "open temporary block dir")

View on GitHub (pinned to 35b8b99117)