{"record":{"id":"05ae5607e36db2e6","repo":"dgraph-io/dgraph","slug":"while-closing-file-s","errorCode":null,"errorMessage":"while closing file: %s","messagePattern":"while closing file: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"worker/backup_handler.go","lineNumber":204,"sourceCode":"func (h *fileHandler) CreateDir(path string) error {\n\tpath = h.JoinPath(path)\n\tif err := os.MkdirAll(path, 0755); err != nil {\n\t\treturn errors.Errorf(\"Create path failed to create path %s, got error: %v\", path, err)\n\t}\n\treturn nil\n}\n\ntype fileSyncer struct {\n\tfp *os.File\n}\n\nfunc (fs *fileSyncer) Write(p []byte) (n int, err error) { return fs.fp.Write(p) }\nfunc (fs *fileSyncer) Close() error {\n\tif err := fs.fp.Sync(); err != nil {\n\t\treturn errors.Wrapf(err, \"while syncing file: %s\", fs.fp.Name())\n\t}\n\terr := fs.fp.Close()\n\treturn errors.Wrapf(err, \"while closing file: %s\", fs.fp.Name())\n}\n\nfunc (h *fileHandler) CreateFile(path string) (io.WriteCloser, error) {\n\tpath = h.JoinPath(path)\n\tfp, err := os.Create(path)\n\treturn &fileSyncer{fp}, errors.Wrapf(err, \"File handler failed to create file %s\", path)\n}\n\nfunc (h *fileHandler) Rename(src, dst string) error {\n\tsrc = h.JoinPath(src)\n\tdst = h.JoinPath(dst)\n\treturn os.Rename(src, dst)\n}\n\n// pathExist checks if a path (file or dir) is found at target.\n// Returns true if found, false otherwise.\nfunc pathExist(path string) bool {\n\t_, err := os.Stat(path)","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/worker/backup_handler.go#L186-L222","documentation":"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.","triggerScenarios":"fs.fp.Close() returns an error: I/O error on close, fd already closed elsewhere (double Close), or descriptor issues during cleanup.","commonSituations":"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.","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."],"exampleFix":"// before\nerr := fs.fp.Close()\nreturn errors.Wrapf(err, \"while closing file: %s\", fs.fp.Name())\n// after\nif err := fs.fp.Close(); err != nil && !errors.Is(err, os.ErrClosed) {\n    return errors.Wrapf(err, \"while closing file: %s\", fs.fp.Name())\n}\nreturn nil","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"err := writeBackup(...)\nif err != nil {\n    if strings.Contains(err.Error(), \"while closing file\") {\n        log.Printf(\"backup close failed: %v — verify fd lifecycle (double close?)\", err)\n    }\n    return err\n}","preventionTips":["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."],"tags":["filesystem","file-close","fd"],"backgroundTag":"file-close-failed","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}