thanos-io/thanos · error
calculate hash
Error message
calculate hash %v
What it means
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.
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.
Example fix
// before
h, err := metadata.CalculateHash(filepath.Join(blockDir, ChunksDirname, f.Name()), hf, logger)
if err != nil {
return nil, errors.Wrapf(err, "calculate hash %v", filepath.Join(ChunksDirname, f.Name()))
}
// after
h, err := metadata.CalculateHash(filepath.Join(blockDir, ChunksDirname, f.Name()), hf, logger)
if err != nil {
return nil, errors.Wrapf(err, "calculate hash %v", filepath.Join(ChunksDirname, f.Name()))
}
// caller side: retry GatherFileStats before failing the whole upload Defensive patterns
Strategy: retry
Validate before calling
for _, name := range chunkNames {
f, err := os.Open(filepath.Join(blockDir, "chunks", name))
if err != nil { return fmt.Errorf("chunk %s unreadable: %w", name, err) }
f.Close()
} Try / catch
if err := retryWithBackoff(ctx, 3, time.Second, func() error {
_, err := block.GatherFileStats(blockDir, hashFunc, logger)
return err
}); err != nil {
return fmt.Errorf("hashing block %s failed after retries: %w", blockDir, err)
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: Block deleted concurrently by compaction/retention while being uploaded; failing disk sector on a specific chunk; NFS timeouts while reading large chunk segments.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/c3d48e72730960e8.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/block/block.go:345
func GatherFileStats(blockDir string, hf metadata.HashFunc, logger log.Logger) (res []metadata.File, _ error) {
files, err := os.ReadDir(filepath.Join(blockDir, ChunksDirname))
if err != nil {
return nil, errors.Wrapf(err, "read dir %v", filepath.Join(blockDir, ChunksDirname))
}
for _, f := range files {
fi, err := f.Info()
if err != nil {
return nil, errors.Wrapf(err, "getting file info %v", filepath.Join(ChunksDirname, f.Name()))
}
mf := metadata.File{
RelPath: filepath.Join(ChunksDirname, f.Name()),
SizeBytes: fi.Size(),
}
if hf != metadata.NoneFunc && !f.IsDir() {
h, err := metadata.CalculateHash(filepath.Join(blockDir, ChunksDirname, f.Name()), hf, logger)
if err != nil {
return nil, errors.Wrapf(err, "calculate hash %v", filepath.Join(ChunksDirname, f.Name()))
}
mf.Hash = &h
}
res = append(res, mf)
}
indexFile, err := os.Stat(filepath.Join(blockDir, IndexFilename))
if err != nil {
return nil, errors.Wrapf(err, "stat %v", filepath.Join(blockDir, IndexFilename))
}
mf := metadata.File{
RelPath: indexFile.Name(),
SizeBytes: indexFile.Size(),
}
if hf != metadata.NoneFunc {
h, err := metadata.CalculateHash(filepath.Join(blockDir, IndexFilename), hf, logger)
if err != nil {
return nil, errors.Wrapf(err, "calculate hash %v", indexFile.Name())View on GitHub (pinned to 35b8b99117)