thanos-io/thanos · error
sync dir
Error message
sync dir
What it means
After creating the FileWriter for the index-header cache file, newBinaryWriter calls df.Sync() on the opened parent directory handle to durably persist the directory entry (the new file's existence). This error wraps the fsync failure on that directory, meaning the OS could not flush the directory metadata to disk.
Solutions
- Move the cache directory onto a local filesystem that supports directory fsync (ext4/xfs).
- Check dmesg / disk health for underlying I/O errors and fix hardware issues.
- If on a network FS that returns EINVAL for dir fsync, reconfigure the storage or patch to skip dir sync there.
- Retry WriteBinary after transient I/O errors.
Example fix
// before
if err := df.Sync(); err != nil {
return nil, errors.Wrap(err, "sync dir")
}
// after
if err := df.Sync(); err != nil {
if errors.Is(err, syscall.EINVAL) {
logger.Warn("directory fsync unsupported on this filesystem; skipping")
} else {
return nil, errors.Wrap(err, "sync dir")
}
} Defensive patterns
Strategy: try-catch
Validate before calling
null
Type guard
null
Try / catch
_, err := WriteBinary(ctx, bkt, id, cachePath, metrics.DownloadDuration)
if err != nil {
if errors.Is(err, syscall.EINVAL) || errors.Is(err, syscall.ENOTSUP) {
// filesystem does not support dir fsync; fall back to memory reader
return NewBinaryReader(ctx, logger, bkt, "", id, sampling, metrics)
}
return errors.Wrap(err, "index header generation")
} Prevention
- Place block cache directories on local ext4/xfs filesystems, not NFS/FUSE.
- Monitor dmesg for I/O errors on cache volumes.
- Avoid containers/seccomp policies that block fsync on directories.
- Retry transient I/O failures with backoff.
When it happens
Trigger: df.Sync() (directory fsync) returns an error inside newBinaryWriter when cacheFilename != '': disk I/O error, filesystem that does not support directory fsync (some network/FUSE filesystems return EINVAL), or the directory handle became invalid.
Common situations: Storing the block cache directory on NFS/CIFS/FUSE mounts that reject fsync on directories; failing disk or full/failing device; container with restricted syscall support.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/75179ac84a1d7b07.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/block/indexheader/binary_reader.go:320
df, err = fileutil.OpenDir(dir)
}
if err != nil {
return nil, err
}
defer runutil.CloseWithErrCapture(&err, df, "dir close")
if err := os.RemoveAll(cacheFilename); err != nil {
return nil, errors.Wrap(err, "remove any existing index at path")
}
var fileWriter *FileWriter
fileWriter, err = NewFileWriter(cacheFilename, len(buf))
if err != nil {
return nil, err
}
if err := df.Sync(); err != nil {
return nil, errors.Wrap(err, "sync dir")
}
binWriter = fileWriter
} else {
binWriter = NewMemoryWriter(id, len(buf))
}
w = &binaryWriter{
writer: binWriter,
// Reusable memory.
buf: encoding.Encbuf{B: buf},
crc32: newCRC32(),
}
w.buf.Reset()
w.buf.PutBE32(MagicIndex)
w.buf.PutByte(BinaryFormatV1)
View on GitHub (pinned to 35b8b99117)