{"record":{"id":"35bf0cec2784423f","repo":"thanos-io/thanos","slug":"remove-any-existing-index-at-path","errorCode":null,"errorMessage":"remove any existing index at path","messagePattern":"remove any existing index at path","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/block/indexheader/binary_reader.go","lineNumber":311,"sourceCode":"\tvar binWriter PosWriter\n\tif cacheFilename != \"\" {\n\t\tdir := filepath.Dir(cacheFilename)\n\n\t\tdf, err := fileutil.OpenDir(dir)\n\t\tif os.IsNotExist(err) {\n\t\t\tif err := os.MkdirAll(dir, os.ModePerm); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tdf, err = fileutil.OpenDir(dir)\n\t\t}\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tdefer runutil.CloseWithErrCapture(&err, df, \"dir close\")\n\n\t\tif err := os.RemoveAll(cacheFilename); err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"remove any existing index at path\")\n\t\t}\n\n\t\tvar fileWriter *FileWriter\n\t\tfileWriter, err = NewFileWriter(cacheFilename, len(buf))\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif err := df.Sync(); err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"sync dir\")\n\t\t}\n\t\tbinWriter = fileWriter\n\t} else {\n\t\tbinWriter = NewMemoryWriter(id, len(buf))\n\t}\n\n\tw = &binaryWriter{\n\t\twriter: binWriter,\n","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/block/indexheader/binary_reader.go#L293-L329","documentation":"newBinaryWriter builds the binary index-header file for a TSDB block. When a cache filename is given, it first deletes any pre-existing file at that path with os.RemoveAll. This error wraps the underlying filesystem error from that removal, so it means the old file (or directory) at the cache path could not be deleted.","triggerScenarios":"os.RemoveAll(cacheFilename) fails inside newBinaryWriter (via WriteBinary with a non-empty cacheFilename): the path exists but the process lacks write permission on the parent directory, the path is a non-empty directory, the filesystem is read-only, or the path is locked by another process.","commonSituations":"Running Thanos/objects store bucket download as a non-root user without permissions on the cache directory; cacheFilename pointing at a directory instead of a file; the cache path residing on a read-only mounted volume; stale files owned by a different UID after a container/user change.","solutions":["Check permissions on the parent directory of cacheFilename and ensure the process user can write/delete there (ls -ld on the dir).","If cacheFilename is a directory, point it to a file path or clear the directory manually.","Remount the volume read-write, or move the cache directory to a writable location.","Stop competing processes holding the file and retry.","If the file is disposable, remove it out-of-band and rerun WriteBinary."],"exampleFix":"// before\nif err := os.RemoveAll(cacheFilename); err != nil {\n    return nil, errors.Wrap(err, \"remove any existing index at path\")\n}\n// after\nif _, statErr := os.Stat(cacheFilename); statErr == nil {\n    if err := os.RemoveAll(cacheFilename); err != nil {\n        return nil, errors.Wrapf(err, \"remove any existing index at path %s (check dir permissions)\", cacheFilename)\n    }\n}","handlingStrategy":"try-catch","validationCode":"if info, err := os.Stat(cachePath); err == nil && !info.Mode().IsRegular() {\n    return fmt.Errorf(\"cache path %s is not a regular file; cannot replace\", cachePath)\n}\nif err := unix.Access(filepath.Dir(cachePath), unix.W_OK); err != nil {\n    return fmt.Errorf(\"no write permission on %s\", filepath.Dir(cachePath))\n}","typeGuard":"func cachePathWritable(path string) bool {\n    dir := filepath.Dir(path)\n    f, err := os.CreateTemp(dir, \".wtest\")\n    if err != nil { return false }\n    f.Close(); os.Remove(f.Name())\n    return true\n}","tryCatchPattern":"hdr, err := NewBinaryReader(ctx, logger, bkt, dir, id, sampling, metrics)\nif err != nil {\n    var pathErr *os.PathError\n    if errors.As(err, &pathErr) && (errors.Is(pathErr.Err, syscall.EACCES) || errors.Is(pathErr.Err, syscall.EPERM)) {\n        // fix permissions or fall back to memory-only reader\n        return NewBinaryReader(ctx, logger, bkt, \"\", id, sampling, metrics)\n    }\n    return err\n}","preventionTips":["Run store-gateway with a user that owns the cache directory.","Never point cacheFilename at a directory.","Keep cache volumes mounted read-write and monitor disk health.","Ensure a single process owns the cache path to avoid contention."],"tags":["filesystem","io","permissions","go"],"backgroundTag":"file-write-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"}