{"record":{"id":"c3d48e72730960e8","repo":"thanos-io/thanos","slug":"calculate-hash-v","errorCode":null,"errorMessage":"calculate hash %v","messagePattern":"calculate hash (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/block/block.go","lineNumber":345,"sourceCode":"func GatherFileStats(blockDir string, hf metadata.HashFunc, logger log.Logger) (res []metadata.File, _ error) {\n\tfiles, err := os.ReadDir(filepath.Join(blockDir, ChunksDirname))\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"read dir %v\", filepath.Join(blockDir, ChunksDirname))\n\t}\n\tfor _, f := range files {\n\t\tfi, err := f.Info()\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrapf(err, \"getting file info %v\", filepath.Join(ChunksDirname, f.Name()))\n\t\t}\n\n\t\tmf := metadata.File{\n\t\t\tRelPath:   filepath.Join(ChunksDirname, f.Name()),\n\t\t\tSizeBytes: fi.Size(),\n\t\t}\n\t\tif hf != metadata.NoneFunc && !f.IsDir() {\n\t\t\th, err := metadata.CalculateHash(filepath.Join(blockDir, ChunksDirname, f.Name()), hf, logger)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrapf(err, \"calculate hash %v\", filepath.Join(ChunksDirname, f.Name()))\n\t\t\t}\n\t\t\tmf.Hash = &h\n\t\t}\n\t\tres = append(res, mf)\n\t}\n\n\tindexFile, err := os.Stat(filepath.Join(blockDir, IndexFilename))\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"stat %v\", filepath.Join(blockDir, IndexFilename))\n\t}\n\tmf := metadata.File{\n\t\tRelPath:   indexFile.Name(),\n\t\tSizeBytes: indexFile.Size(),\n\t}\n\tif hf != metadata.NoneFunc {\n\t\th, err := metadata.CalculateHash(filepath.Join(blockDir, IndexFilename), hf, logger)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrapf(err, \"calculate hash %v\", indexFile.Name())","sourceCodeStart":327,"sourceCodeEnd":363,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/block/block.go#L327-L363","documentation":"GatherFileStats computes a content hash for each non-directory chunk file using metadata.CalculateHash and wraps its failure with this message. This means reading + hashing (hashfunc over the file contents) of one chunk file failed — usually an I/O error while reading the chunk.","triggerScenarios":"metadata.CalculateHash on <blockDir>/chunks/<file> returned an error — the file disappeared or became unreadable during hashing, disk I/O error, or the provided hash function (e.g., SHA256) hit a read failure on a large/sparse file.","commonSituations":"Block deleted concurrently by compaction/retention while being uploaded; failing disk sector on a specific chunk; NFS timeouts while reading large chunk segments.","solutions":["Re-read the specific chunk file manually to confirm it's readable (cat/sha256sum the file).","Prevent concurrent modification: ensure the block is not deleted/compacted during upload.","Check disk health (dmesg, SMART) if I/O errors repeat on the same file.","Retry the upload; transient I/O issues may clear."],"exampleFix":"// before\nh, err := metadata.CalculateHash(filepath.Join(blockDir, ChunksDirname, f.Name()), hf, logger)\nif err != nil {\n\treturn nil, errors.Wrapf(err, \"calculate hash %v\", filepath.Join(ChunksDirname, f.Name()))\n}\n// after\nh, err := metadata.CalculateHash(filepath.Join(blockDir, ChunksDirname, f.Name()), hf, logger)\nif err != nil {\n\treturn nil, errors.Wrapf(err, \"calculate hash %v\", filepath.Join(ChunksDirname, f.Name()))\n}\n// caller side: retry GatherFileStats before failing the whole upload","handlingStrategy":"retry","validationCode":"for _, name := range chunkNames {\n\tf, err := os.Open(filepath.Join(blockDir, \"chunks\", name))\n\tif err != nil { return fmt.Errorf(\"chunk %s unreadable: %w\", name, err) }\n\tf.Close()\n}","typeGuard":null,"tryCatchPattern":"if err := retryWithBackoff(ctx, 3, time.Second, func() error {\n\t_, err := block.GatherFileStats(blockDir, hashFunc, logger)\n\treturn err\n}); err != nil {\n\treturn fmt.Errorf(\"hashing block %s failed after retries: %w\", blockDir, err)\n}","preventionTips":["Ensure blocks are immutable during hashing/upload (no concurrent compaction).","Keep chunk files on healthy local disks; watch SMART/dmesg for I/O errors.","Prefer a hash function (SHA256) that is supported and benchmarked on your hardware.","Retry hashing on transient I/O failures before failing the upload."],"tags":["filesystem","hashing","thanos"],"backgroundTag":"file-read-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"}