{"record":{"id":"3f68c510acedb5e2","repo":"benbjohnson/litestream","slug":"create-parent-directory-w","errorCode":null,"errorMessage":"create parent directory: %w","messagePattern":"create parent directory: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"db.go","lineNumber":749,"sourceCode":"// database file does not exist. If no backup is available, it returns nil and\n// a fresh database will be created on Open(). Must be called before Open().\nfunc (db *DB) EnsureExists(ctx context.Context) error {\n\tif db.Replica == nil {\n\t\treturn fmt.Errorf(\"no replica configured\")\n\t}\n\tif db.Replica.Client == nil {\n\t\treturn fmt.Errorf(\"no replica client configured\")\n\t}\n\n\tif _, err := os.Stat(db.Path()); err == nil {\n\t\treturn nil\n\t} else if !os.IsNotExist(err) {\n\t\treturn fmt.Errorf(\"stat database: %w\", err)\n\t}\n\n\tif dir := filepath.Dir(db.Path()); dir != \".\" {\n\t\tif err := os.MkdirAll(dir, 0o750); err != nil {\n\t\t\treturn fmt.Errorf(\"create parent directory: %w\", err)\n\t\t}\n\t}\n\n\topt := NewRestoreOptions()\n\topt.OutputPath = db.Path()\n\topt.IntegrityCheck = IntegrityCheckQuick\n\n\tif err := db.Replica.Restore(ctx, opt); err != nil {\n\t\tif errors.Is(err, ErrTxNotAvailable) || errors.Is(err, ErrNoSnapshots) {\n\t\t\tdb.Logger.Debug(\"no backup found, will create fresh database\")\n\t\t\treturn nil\n\t\t}\n\t\treturn fmt.Errorf(\"restore from backup: %w\", err)\n\t}\n\n\tdb.Logger.Info(\"database restored from backup\", \"path\", db.Path())\n\treturn nil\n}","sourceCodeStart":731,"sourceCodeEnd":767,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/db.go#L731-L767","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"dir := filepath.Dir(db.Path())\nif dir != \".\" {\n    if err := os.MkdirAll(dir, 0o750); err != nil {\n        return fmt.Errorf(\"preflight mkdir failed: %w\", err)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := db.EnsureExists(ctx); err != nil {\n    var pe *fs.PathError\n    if errors.As(err, &pe) && errors.Is(pe.Err, syscall.EACCES) {\n        log.Error(\"mkdir permission denied\", \"path\", pe.Path)\n    }\n    return err\n}","preventionTips":["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."],"tags":["filesystem","mkdir","permissions"],"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"}