thanos-io/thanos · error
close temporary dir
Error message
close temporary dir
What it means
Flush fails when df.Close() cannot close the temporary block directory handle after a successful sync. The close is required before renaming the tmp dir into place (particularly on Windows, where open handles prevent renames).
Solutions
- Check open file descriptor limits (ulimit -n) and close leaked handles elsewhere in the app.
- Retry the Flush; ensure no double-close of the same dir handle.
- On Windows, confirm no other process holds an open handle inside the tmp dir.
- Discard the tmp dir and re-create the block if the close keeps failing.
Example fix
// before $ ulimit -n 1024 // after $ ulimit -n 65536
Defensive patterns
Strategy: retry
Validate before calling
// ensure fd headroom
var lim unix.Rlimit
if unix.Getrlimit(unix.RLIMIT_NOFILE, &lim) == nil && lim.Cur < 4096 {
lim.Cur = 4096
unix.Setrlimit(unix.RLIMIT_NOFILE, &lim)
} Try / catch
if _, err := d.Flush(ctx); err != nil {
if strings.Contains(err.Error(), "close temporary dir") {
// fd/handle issue: GC and retry once, else re-create block
runtime.GC()
return fmt.Errorf("closing tmp dir failed: %w", err)
}
return err
} Prevention
- Raise ulimit -n on hosts doing heavy block IO.
- Avoid holding duplicate handles to the block tmp dir.
- On Windows, ensure no other process opens files inside the tmp dir during flush.
When it happens
Trigger: df.Close() returning an error — typically fd exhaustion-related state issues, double-close conditions, or OS-level errors on the directory handle.
Common situations: Running out of file descriptors leading to handle corruption; platform quirks on Windows where the dir must be closed before rename; rare kernel-level errors.
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/a96902f03c8908ff.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/block/writer.go:128
}
}()
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 {
d.closers = nil
return tsdb.BlockStats{}, err
}
d.closers = nil
// Block files successfully written, make them visible by moving files from tmp dir.
if err := fileutil.Replace(filepath.Join(d.bTmp, IndexFilename), filepath.Join(d.bDir, IndexFilename)); err != nil {
return tsdb.BlockStats{}, errors.Wrap(err, "replace index file")
}
if err := fileutil.Replace(filepath.Join(d.bTmp, ChunksDirname), filepath.Join(d.bDir, ChunksDirname)); err != nil {
return tsdb.BlockStats{}, errors.Wrap(err, "replace chunks dir")
}
return d.stats, nil
}View on GitHub (pinned to 35b8b99117)