{"record":{"id":"0a83809d89f5e3f1","repo":"benbjohnson/litestream","slug":"create-hydration-directory-w","errorCode":null,"errorMessage":"create hydration directory: %w","messagePattern":"create hydration directory: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"vfs.go","lineNumber":681,"sourceCode":"\tclient     ReplicaClient\n\tlogger     *slog.Logger\n}\n\n// NewHydrator creates a new Hydrator instance.\nfunc NewHydrator(path string, persistent bool, pageSize uint32, client ReplicaClient, logger *slog.Logger) *Hydrator {\n\treturn &Hydrator{\n\t\tpath:       path,\n\t\tpersistent: persistent,\n\t\tpageSize:   pageSize,\n\t\tclient:     client,\n\t\tlogger:     logger,\n\t}\n}\n\n// Init opens or creates the hydration file.\nfunc (h *Hydrator) Init() error {\n\tif err := os.MkdirAll(filepath.Dir(h.path), 0755); err != nil {\n\t\treturn fmt.Errorf(\"create hydration directory: %w\", err)\n\t}\n\n\tif h.persistent {\n\t\tif txid, err := h.loadMeta(); err == nil {\n\t\t\tif _, statErr := os.Stat(h.path); statErr == nil {\n\t\t\t\tfile, err := os.OpenFile(h.path, os.O_RDWR, 0600)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"open persistent hydration file: %w\", err)\n\t\t\t\t}\n\t\t\t\th.file = file\n\t\t\t\th.txid = txid\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}\n\t\tif err := os.Remove(h.metaPath()); err != nil && !os.IsNotExist(err) {\n\t\t\treturn fmt.Errorf(\"remove stale hydration meta: %w\", err)\n\t\t}\n\t}","sourceCodeStart":663,"sourceCodeEnd":699,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/vfs.go#L663-L699","documentation":"Hydrator.Init creates the parent directory of the hydration file with os.MkdirAll before opening or creating the file. This error wraps that failure. Hydration stores a local materialized copy of the remote database, so its directory must exist and be writable before initialization can proceed.","triggerScenarios":"Calling Hydrator.Init (via opening the DB with hydration enabled) when the directory containing the configured hydration path cannot be created — missing permission on the parent, path component is a file, or read-only filesystem.","commonSituations":"hydrationPath pointing under a read-only mount; typo making the parent path contain an existing file (e.g. /data/db where db is a file); running under a non-root container user with no write access to /var/lib/litestream.","solutions":["Create the parent directory manually and chown it to the process user (mkdir -p <dir> && chown app:app <dir>).","Point hydrationPath at a location the process can write (e.g. a mounted writable volume in containers).","Check that no path component is an existing regular file; rename or remove it.","If the mount is read-only, remount rw or select another directory."],"exampleFix":"// before\nhydrator := NewHydrator(\"/var/lib/litestream/hydration/app.db\") // no permission\n\n// after\nos.MkdirAll(\"/var/lib/litestream/hydration\", 0o755) // as setup step, with correct ownership\nhydrator := NewHydrator(\"/var/lib/litestream/hydration/app.db\")","handlingStrategy":"validation","validationCode":"dir := filepath.Dir(hydrationPath)\nif err := os.MkdirAll(dir, 0o755); err != nil {\n    return fmt.Errorf(\"hydration dir %q not preparable: %w\", dir, err)\n}\nprobe, err := os.CreateTemp(dir, \"probe-*\")\nif err != nil { return err }\nprobe.Close(); os.Remove(probe.Name())","typeGuard":null,"tryCatchPattern":"if err := hydrator.Init(); err != nil && strings.Contains(err.Error(), \"create hydration directory\") {\n    // fix ownership/permissions on dir, then retry Init\n}","preventionTips":["Provision and chown the hydration directory at deploy time.","Point hydrationPath at a writable persistent volume, not a read-only mount.","Ensure no path component collides with an existing file.","Use the same user for all processes touching the hydration dir."],"tags":["go","filesystem","hydration","mkdir"],"backgroundTag":"mkdir-permission-denied","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"}