thanos-io/thanos · error
open temporary block dir
Error message
open temporary block dir
What it means
Flush fails when fileutil.OpenDir cannot open the temporary block directory for reading. Flush finalizes the block by syncing, closing writers, and renaming the tmp dir; if the tmp dir cannot even be opened, finalization cannot proceed and the block is not published.
Solutions
- Ensure no other process concurrently removes the <block>/tmp-for-creation directory.
- Confirm Flush is called on the same DiskWriter instance/dir used for writes.
- Check filesystem permissions and open-file limits (ulimit -n).
- If the block write failed earlier, discard and re-create the block instead of flushing.
Example fix
// before // janitor goroutine: os.RemoveAll(tmpDir) while Flush is running // after // guard: only remove tmpDir if writer flush failed and is not in progress
Defensive patterns
Strategy: retry
Validate before calling
tmpDir := filepath.Join(bdir, "tmp-for-creation")
if fi, err := os.Stat(tmpDir); err != nil || !fi.IsDir() {
return fmt.Errorf("tmp dir %s missing before flush", tmpDir)
} Try / catch
if _, err := d.Flush(ctx); err != nil {
if strings.Contains(err.Error(), "open temporary block dir") {
// transient removal race: rebuild block
return fmt.Errorf("tmp dir vanished during flush; re-run compaction: %w", err)
}
return err
} Prevention
- Never run concurrent writers or janitors on the same block directory.
- Raise open-file limits (ulimit -n) on compaction hosts.
- Only remove tmp-for-creation dirs when no Flush is in progress.
When it happens
Trigger: fileutil.OpenDir(d.bTmp) failing because the temp block dir was deleted (e.g. by concurrent cleanup), was never created, the path changed, or an OS-level open error occurred (permissions, fd exhaustion).
Common situations: Two compactions/uploads racing on the same block dir and one removing the tmp folder; tmp dir cleaned by a janitor mid-flush; too many open files; wrong bdir passed so bTmp never existed.
Related errors
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/4be40bfe4de59538.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/block/writer.go:114
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")
}
defer func() {
if df != nil {
err = tsdb_errors.NewMulti(err, df.Close()).Err()
}
}()
if err := df.Sync(); err != nil {
return tsdb.BlockStats{}, errors.Wrap(err, "sync temporary dir file")
}
// Close temp dir before rename block dir (for windows platform).
if err = df.Close(); err != nil {
return tsdb.BlockStats{}, errors.Wrap(err, "close temporary dir")
}
df = nil
if err := tsdb_errors.CloseAll(d.closers); err != nil {View on GitHub (pinned to 35b8b99117)