{"record":{"id":"4f1e61ea9ced00d2","repo":"benbjohnson/litestream","slug":"sync-hydration-meta-directory-w","errorCode":null,"errorMessage":"sync hydration meta directory: %w","messagePattern":"sync hydration meta directory: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"vfs.go","lineNumber":1024,"sourceCode":"\t\tif removeErr := os.Remove(tmpPath); removeErr != nil {\n\t\t\th.logger.Warn(\"failed to remove temp meta file during cleanup\", \"error\", removeErr)\n\t\t}\n\t\treturn fmt.Errorf(\"sync temp meta file: %w\", err)\n\t}\n\tif err := tmp.Close(); err != nil {\n\t\tif removeErr := os.Remove(tmpPath); removeErr != nil {\n\t\t\th.logger.Warn(\"failed to remove temp meta file during cleanup\", \"error\", removeErr)\n\t\t}\n\t\treturn fmt.Errorf(\"close temp meta file: %w\", err)\n\t}\n\tif err := os.Rename(tmpPath, h.metaPath()); err != nil {\n\t\tif removeErr := os.Remove(tmpPath); removeErr != nil {\n\t\t\th.logger.Warn(\"failed to remove temp meta file during cleanup\", \"error\", removeErr)\n\t\t}\n\t\treturn fmt.Errorf(\"rename hydration meta: %w\", err)\n\t}\n\tif err := syncDir(filepath.Dir(h.metaPath())); err != nil {\n\t\treturn fmt.Errorf(\"sync hydration meta directory: %w\", err)\n\t}\n\treturn nil\n}\n\nfunc syncDir(path string) error {\n\tdir, err := os.Open(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer dir.Close()\n\treturn dir.Sync()\n}\n\nfunc NewVFSFile(client ReplicaClient, name string, logger *slog.Logger) *VFSFile {\n\tf := &VFSFile{\n\t\tclient:       client,\n\t\tname:         name,\n\t\tindex:        make(map[uint32]ltx.PageIndexElem),","sourceCodeStart":1006,"sourceCodeEnd":1042,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/vfs.go#L1006-L1042","documentation":"Raised by the VFS hydrator when fsync-ing the directory that contains the hydration meta file fails after renaming a temporary meta file into place. The rename succeeded but the directory entry could not be flushed to durable storage, so a crash could leave the hydration state file missing or stale. The library throws this to guarantee the meta file's existence is durable before proceeding.","triggerScenarios":"os.Open(dir) fails (directory removed/permissions) or the Sync() on the directory fd fails (EIO from disk, EROFS, ENOSPC on metadata) during hydration meta finalization.","commonSituations":"Disk full or failing disk on the hydration path; hydration directory on a filesystem that does not support fsync (some network/overlay mounts); permissions changed on the hydration directory mid-run.","solutions":["Check the health and free space of the filesystem holding the hydration directory (dmesg for I/O errors)","Verify the hydration directory still exists and the process has write/search permissions on it","Move the hydration path to a reliable local filesystem that supports fsync (not NFS/overlayfs)","Retry open; if persistent, disable hydration (unset hydrationPath) and continue without it"],"exampleFix":"// before\nif err := syncDir(filepath.Dir(h.metaPath())); err != nil {\n    return fmt.Errorf(\"sync hydration meta directory: %w\", err)\n}\n// after\nif err := syncDir(filepath.Dir(h.metaPath())); err != nil {\n    h.logger.Warn(\"hydration meta dir sync failed, hydration may be stale after crash\", \"error\", err)\n    // or relocate hydrationPath to local durable storage\n}","handlingStrategy":"try-catch","validationCode":"// Go: verify hydration dir is usable before enabling hydration\nif fi, err := os.Stat(hydrationDir); err != nil || !fi.IsDir() { /* disable hydration or fix path */ }","typeGuard":"func hydrationDirOK(dir string) bool { fi, err := os.Stat(dir); return err == nil && fi.IsDir() }","tryCatchPattern":"if err := file.Open(ctx); err != nil {\n    if strings.Contains(err.Error(), \"sync hydration meta directory\") {\n        logger.Warn(\"hydration durability failed; continuing without hydration\", \"error\", err)\n    } else { return err }\n}","preventionTips":["Put hydrationPath on local, fsync-capable storage","Monitor disk health and free space on the hydration volume","Set directory permissions before enabling hydration"],"tags":["filesystem","fsync","durability","hydration"],"backgroundTag":"file-write-failed","analyzedSha":"4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3","analyzedAt":"2026-09-06T18:29:25.564Z","contentChangedAt":"2026-09-06T18:29:25.564Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}