benbjohnson/litestream · error
open persistent hydration file: %w
Error message
open persistent hydration file: %w
What it means
When the Hydrator is persistent and both a valid metadata file (with a txid) and an existing hydration file are found, Init reopens the hydration file with os.OpenFile(O_RDWR). This error wraps the failure to reopen that existing file. It means a prior hydration run left state on disk that now cannot be opened read-write.
Source
Thrown at vfs.go:689
persistent: persistent,
pageSize: pageSize,
client: client,
logger: logger,
}
}
// Init opens or creates the hydration file.
func (h *Hydrator) Init() error {
if err := os.MkdirAll(filepath.Dir(h.path), 0755); err != nil {
return fmt.Errorf("create hydration directory: %w", err)
}
if h.persistent {
if txid, err := h.loadMeta(); err == nil {
if _, statErr := os.Stat(h.path); statErr == nil {
file, err := os.OpenFile(h.path, os.O_RDWR, 0600)
if err != nil {
return fmt.Errorf("open persistent hydration file: %w", err)
}
h.file = file
h.txid = txid
return nil
}
}
if err := os.Remove(h.metaPath()); err != nil && !os.IsNotExist(err) {
return fmt.Errorf("remove stale hydration meta: %w", err)
}
}
file, err := os.OpenFile(h.path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return fmt.Errorf("create hydration file: %w", err)
}
h.file = file
return nil
}View on GitHub (pinned to 4ed7a308f6)
Solutions
- Fix permissions on the existing hydration file so the process user can read/write it (chown/chmod 600).
- Run all processes touching the hydration dir under the same user (avoid root-then-user switches).
- Delete the stale hydration file and meta so the next Init recreates them, accepting a re-hydration.
- Check for filesystem errors with dmesg/journalctl if permissions look correct.
Example fix
// before sudo litestream ... // hydration file created as root:0600 // after sudo chown app:app /var/lib/litestream/hydration/* # or run litestream always as app user
Defensive patterns
Strategy: validation
Validate before calling
p := hydrator.Path()
if fi, err := os.Stat(p); err == nil {
f, err := os.OpenFile(p, os.O_RDWR, 0)
if err != nil { /* fix perms or delete stale file before Init */ }
f.Close()
} Try / catch
if err := hydrator.Init(); err != nil && strings.Contains(err.Error(), "open persistent hydration file") {
// chown/chmod the file or remove it + meta to force re-hydration
} Prevention
- Run every process touching the hydration dir as the same user.
- Avoid sudo for one-off runs that create root-owned hydration files.
- Backup tooling must preserve ownership/permissions (0600).
- Monitor for stale hydration state after crashes and clean it deliberately.
When it happens
Trigger: Init on a persistent hydrator where hydration.db exists and meta loads successfully, but os.OpenFile(path, O_RDWR, 0600) fails — file owned by another user, permission bits changed, or the file was replaced by a symlink/device with restrictive permissions.
Common situations: Previous run as root created the hydration file; current run as unprivileged user cannot open it read-write; backup/restore tooling altered file permissions; disk errors surfacing as open failures.
Understand the failure class
Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.
Related errors
- create hydration directory: %w
- remove stale hydration meta: %w
- create hydration file: %w
- open buffer file: %w
- open wal file: %w
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/fec9291519809efc.
Report an issue: GitHub.