{"record":{"id":"72f3b809f00070ee","repo":"thanos-io/thanos","slug":"open-index-writer-72f3b8","errorCode":null,"errorMessage":"open index writer","messagePattern":"open index writer","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/block/writer.go","lineNumber":96,"sourceCode":"\n\tif err = os.RemoveAll(bTmp); err != nil {\n\t\treturn nil, err\n\t}\n\tif err = os.MkdirAll(bTmp, 0750); err != nil {\n\t\treturn nil, err\n\t}\n\n\tchunkw, err := chunks.NewWriter(filepath.Join(bTmp, ChunksDirname))\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"open chunk writer\")\n\t}\n\td.closers = append(d.closers, chunkw)\n\n\t// TODO(bwplotka): Setup instrumentedChunkWriter if we want to upstream this code.\n\n\tindexw, err := index.NewWriter(ctx, filepath.Join(bTmp, IndexFilename))\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"open index writer\")\n\t}\n\td.closers = append(d.closers, indexw)\n\td.statsGatheringSeriesWriter = statsGatheringSeriesWriter{iw: indexw, cw: chunkw}\n\treturn d, nil\n}\n\nfunc (d *DiskWriter) Flush() (_ tsdb.BlockStats, err error) {\n\tdefer func() {\n\t\tif err != nil {\n\t\t\terr = tsdb_errors.NewMulti(err, tsdb_errors.CloseAll(d.closers)).Err()\n\t\t\tif err := os.RemoveAll(d.bTmp); err != nil {\n\t\t\t\tlevel.Error(d.logger).Log(\"msg\", \"removed tmp folder failed after block(s) write\", \"err\", err.Error())\n\t\t\t}\n\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\")","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/block/writer.go#L78-L114","documentation":"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.","triggerScenarios":"index.NewWriter(ctx, <bTmp>/index) failing due to OS-level open/creation errors: permission denied, disk full, path conflicts, or invalid context already cancelled.","commonSituations":"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.","solutions":["Check free disk space — index writing needs headroom after chunks.","Verify write permissions on the block temp directory.","Ensure no leftover file exists at <bTmp>/index blocking the new writer.","Pass a live (non-cancelled) context to NewDiskWriter."],"exampleFix":"// before\nd, err := NewDiskWriter(ctx, cancelledCtx, bdir) // ctx already cancelled\n// after\nd, err := NewDiskWriter(ctx, context.Background(), bdir)","handlingStrategy":"try-catch","validationCode":"if err := ctx.Err(); err != nil {\n    return fmt.Errorf(\"context cancelled before block write: %w\", err)\n}\nif free, err := diskFree(bdir); err == nil && free < minRequiredBytes {\n    return fmt.Errorf(\"insufficient disk space: %d bytes free\", free)\n}","typeGuard":null,"tryCatchPattern":"d, err := block.NewDiskWriter(ctx, bdir, logger)\nif err != nil {\n    if strings.Contains(err.Error(), \"open index writer\") {\n        return fmt.Errorf(\"cannot create index writer (disk space/ctx?): %w\", err)\n    }\n    return err\n}","preventionTips":["Monitor free disk space; index writes need headroom after chunks.","Always pass a live context to NewDiskWriter and keep it alive through Flush.","Remove leftover 'index' files from interrupted tmp dirs."],"tags":["go","block-writer","file-open-failed","filesystem"],"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"}