benbjohnson/litestream · error
create parent directory: %w
Error message
create parent directory: %w
What it means
Before restoring, DB.EnsureExists(ctx) creates the parent directory of db.Path() with os.MkdirAll(dir, 0o750). If that fails, it wraps the error as "create parent directory". Typical causes are filesystem permission denied, read-only mounts, or an invalid path component.
Source
Thrown at db.go:749
// database file does not exist. If no backup is available, it returns nil and
// a fresh database will be created on Open(). Must be called before Open().
func (db *DB) EnsureExists(ctx context.Context) error {
if db.Replica == nil {
return fmt.Errorf("no replica configured")
}
if db.Replica.Client == nil {
return fmt.Errorf("no replica client configured")
}
if _, err := os.Stat(db.Path()); err == nil {
return nil
} else if !os.IsNotExist(err) {
return fmt.Errorf("stat database: %w", err)
}
if dir := filepath.Dir(db.Path()); dir != "." {
if err := os.MkdirAll(dir, 0o750); err != nil {
return fmt.Errorf("create parent directory: %w", err)
}
}
opt := NewRestoreOptions()
opt.OutputPath = db.Path()
opt.IntegrityCheck = IntegrityCheckQuick
if err := db.Replica.Restore(ctx, opt); err != nil {
if errors.Is(err, ErrTxNotAvailable) || errors.Is(err, ErrNoSnapshots) {
db.Logger.Debug("no backup found, will create fresh database")
return nil
}
return fmt.Errorf("restore from backup: %w", err)
}
db.Logger.Info("database restored from backup", "path", db.Path())
return nil
}View on GitHub (pinned to 4ed7a308f6)
Solutions
- Read the wrapped errno: EACCES -> fix permissions, EROFS -> mount writable volume, ENOTDIR -> remove/fix the conflicting file.
- chown/chmod the data directory for the litestream process user (or run the container with the right UID).
- Ensure the volume containing the db path is writable and mounted.
- Pre-create the parent directory in deployment (init container/entrypoint) so MkdirAll is a no-op.
Defensive patterns
Strategy: validation
Validate before calling
dir := filepath.Dir(db.Path())
if dir != "." {
if err := os.MkdirAll(dir, 0o750); err != nil {
return fmt.Errorf("preflight mkdir failed: %w", err)
}
} Try / catch
if err := db.EnsureExists(ctx); err != nil {
var pe *fs.PathError
if errors.As(err, &pe) && errors.Is(pe.Err, syscall.EACCES) {
log.Error("mkdir permission denied", "path", pe.Path)
}
return err
} Prevention
- Pre-create the data directory with correct ownership in deployment (init container/entrypoint).
- Ensure the volume is mounted read-write before starting litestream.
- Run the container with a UID matching the data directory owner.
- Keep db paths short and free of file-where-directory conflicts.
When it happens
Trigger: os.MkdirAll failing while creating the db's parent directory: parent not writable by the litestream user, read-only filesystem/volume, ENAMETOOLONG, or a non-directory existing at some path component.
Common situations: Container running as non-root with the data volume owned by root; read-only rootfs with the db path on /; db path configured under a directory that exists as a regular file; too-long paths from deeply nested $PID-expanded config paths.
Understand the failure class
Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.
Related errors
- recreate L0 directory: %w
- cannot access output path: %w
- cannot access SQLite sidecar path: %w
- remove existing output path: %w
- remove ltx directory: %w
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/3f68c510acedb5e2.
Report an issue: GitHub.