dgraph-io/dgraph · error
while closing file: %s
Error message
while closing file: %s
What it means
After a successful Sync, fileSyncer.Close closes the file descriptor and wraps any error as 'while closing file: <name>'. This is the file-descriptor close failure (e.g. EIO on close, EBADF), distinct from the sync failure at the same site.
Source
Thrown at worker/backup_handler.go:204
func (h *fileHandler) CreateDir(path string) error {
path = h.JoinPath(path)
if err := os.MkdirAll(path, 0755); err != nil {
return errors.Errorf("Create path failed to create path %s, got error: %v", path, err)
}
return nil
}
type fileSyncer struct {
fp *os.File
}
func (fs *fileSyncer) Write(p []byte) (n int, err error) { return fs.fp.Write(p) }
func (fs *fileSyncer) Close() error {
if err := fs.fp.Sync(); err != nil {
return errors.Wrapf(err, "while syncing file: %s", fs.fp.Name())
}
err := fs.fp.Close()
return errors.Wrapf(err, "while closing file: %s", fs.fp.Name())
}
func (h *fileHandler) CreateFile(path string) (io.WriteCloser, error) {
path = h.JoinPath(path)
fp, err := os.Create(path)
return &fileSyncer{fp}, errors.Wrapf(err, "File handler failed to create file %s", path)
}
func (h *fileHandler) Rename(src, dst string) error {
src = h.JoinPath(src)
dst = h.JoinPath(dst)
return os.Rename(src, dst)
}
// pathExist checks if a path (file or dir) is found at target.
// Returns true if found, false otherwise.
func pathExist(path string) bool {
_, err := os.Stat(path)View on GitHub (pinned to 759e242be6)
Solutions
- Check the wrapped cause and whether the fd was already closed (double-Close race).
- Ensure callers close the writer exactly once (defer Close with a single owner).
- Check kernel logs for EIO on the device; replace failing hardware.
- Re-run the backup after fixing storage state.
Example fix
// before
err := fs.fp.Close()
return errors.Wrapf(err, "while closing file: %s", fs.fp.Name())
// after
if err := fs.fp.Close(); err != nil && !errors.Is(err, os.ErrClosed) {
return errors.Wrapf(err, "while closing file: %s", fs.fp.Name())
}
return nil Defensive patterns
Strategy: try-catch
Try / catch
err := writeBackup(...)
if err != nil {
if strings.Contains(err.Error(), "while closing file") {
log.Printf("backup close failed: %v — verify fd lifecycle (double close?)", err)
}
return err
} Prevention
- Use sync.Once or explicit ownership rules to guarantee a single Close.
- Never close the writer returned by CreateFile from multiple goroutines.
- Audit code paths where a timeout may cause a second Close.
- Watch fd usage (lsof) for leaked or prematurely closed descriptors.
When it happens
Trigger: fs.fp.Close() returns an error: I/O error on close, fd already closed elsewhere (double Close), or descriptor issues during cleanup.
Common situations: Double-close of the same writer by caller and library code; failing disk reporting errors at close; NFS stale handles; use-after-timeout where another goroutine already closed the fd.
Related errors
- error while creating debug file: %s
- error while creating temporary directory: %s
- error while archiving debuginfo directory: %s
- p directory does not exist for group [%d]: [%s]
- failed to open BadgerDB at [%v]: %v
AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01).
Data as JSON: /api/errors/05ae5607e36db2e6.
Report an issue: GitHub.