{"record":{"id":"a96902f03c8908ff","repo":"thanos-io/thanos","slug":"close-temporary-dir","errorCode":null,"errorMessage":"close temporary dir","messagePattern":"close temporary dir","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/block/writer.go","lineNumber":128,"sourceCode":"\t\t}\n\t}()\n\tdf, err := fileutil.OpenDir(d.bTmp)\n\tif err != nil {\n\t\treturn tsdb.BlockStats{}, errors.Wrap(err, \"open temporary block dir\")\n\t}\n\tdefer func() {\n\t\tif df != nil {\n\t\t\terr = tsdb_errors.NewMulti(err, df.Close()).Err()\n\t\t}\n\t}()\n\n\tif err := df.Sync(); err != nil {\n\t\treturn tsdb.BlockStats{}, errors.Wrap(err, \"sync temporary dir file\")\n\t}\n\n\t// Close temp dir before rename block dir (for windows platform).\n\tif err = df.Close(); err != nil {\n\t\treturn tsdb.BlockStats{}, errors.Wrap(err, \"close temporary dir\")\n\t}\n\tdf = nil\n\n\tif err := tsdb_errors.CloseAll(d.closers); err != nil {\n\t\td.closers = nil\n\t\treturn tsdb.BlockStats{}, err\n\t}\n\td.closers = nil\n\n\t// Block files successfully written, make them visible by moving files from tmp dir.\n\tif err := fileutil.Replace(filepath.Join(d.bTmp, IndexFilename), filepath.Join(d.bDir, IndexFilename)); err != nil {\n\t\treturn tsdb.BlockStats{}, errors.Wrap(err, \"replace index file\")\n\t}\n\tif err := fileutil.Replace(filepath.Join(d.bTmp, ChunksDirname), filepath.Join(d.bDir, ChunksDirname)); err != nil {\n\t\treturn tsdb.BlockStats{}, errors.Wrap(err, \"replace chunks dir\")\n\t}\n\treturn d.stats, nil\n}","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/block/writer.go#L110-L146","documentation":"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).","triggerScenarios":"df.Close() returning an error — typically fd exhaustion-related state issues, double-close conditions, or OS-level errors on the directory handle.","commonSituations":"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.","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."],"exampleFix":"// before\n$ ulimit -n 1024\n// after\n$ ulimit -n 65536","handlingStrategy":"retry","validationCode":"// ensure fd headroom\nvar lim unix.Rlimit\nif unix.Getrlimit(unix.RLIMIT_NOFILE, &lim) == nil && lim.Cur < 4096 {\n    lim.Cur = 4096\n    unix.Setrlimit(unix.RLIMIT_NOFILE, &lim)\n}","typeGuard":null,"tryCatchPattern":"if _, err := d.Flush(ctx); err != nil {\n    if strings.Contains(err.Error(), \"close temporary dir\") {\n        // fd/handle issue: GC and retry once, else re-create block\n        runtime.GC()\n        return fmt.Errorf(\"closing tmp dir failed: %w\", err)\n    }\n    return err\n}","preventionTips":["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."],"tags":["go","block-writer","filesystem","file-handle"],"backgroundTag":"file-open-failed","analyzedSha":"35b8b991177def87ed52dcf10f9b6d87f07282c8","analyzedAt":"2026-09-07T01:49:59.689Z","contentChangedAt":"2026-09-07T01:49:59.689Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}