{"record":{"id":"a4dcc50c7c7dc16a","repo":"gastownhall/beads","slug":"uow-creating-server-root-directory-w-a4dcc5","errorCode":null,"errorMessage":"uow: creating server root directory: %w","messagePattern":"uow: creating server root directory: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/uow/external_doltserver_provider.go","lineNumber":51,"sourceCode":"\t\tidleTimeout = defaultProxyIdleTimeout\n\t}\n\tif database == \"\" {\n\t\treturn nil, fmt.Errorf(\"uow: database name must not be empty (caller should default to %q)\", \"beads\")\n\t}\n\tif rootUser == \"\" {\n\t\treturn nil, fmt.Errorf(\"uow: rootUser must not be empty\")\n\t}\n\tif err := external.Validate(); err != nil {\n\t\treturn nil, fmt.Errorf(\"uow: external: %w\", err)\n\t}\n\n\tabsServerRootDir, err := filepath.Abs(serverRootDir)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"uow: resolving server root dir: %w\", err)\n\t}\n\n\tif err := os.MkdirAll(absServerRootDir, config.BeadsDirPerm); err != nil {\n\t\treturn nil, fmt.Errorf(\"uow: creating server root directory: %w\", err)\n\t}\n\n\ttlsConfigName, err := registerExternalTLSConfig(external)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"uow: external TLS: %w\", err)\n\t}\n\n\tep, err := proxy.GetCreateDatabaseProxyServerEndpoint(absServerRootDir, proxy.OpenOpts{\n\t\tBackend:     proxy.BackendExternal,\n\t\tLogFilePath: serverLogFilePath,\n\t\tExternal:    external,\n\t\tIdleTimeout: idleTimeout,\n\t\tPort:        proxyPort,\n\t})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"uow: get proxy endpoint: %w\", err)\n\t}\n","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/uow/external_doltserver_provider.go#L33-L69","documentation":"After resolving the server root path, the provider ensures the directory tree exists via os.MkdirAll with config.BeadsDirPerm. This error wraps an MkdirAll failure, meaning the provider could not create (or could not write to) the directory where the external Dolt server's data and files live. It is a filesystem permission or environment problem, not a logic error.","triggerScenarios":"os.MkdirAll(absServerRootDir, config.BeadsDirPerm) fails: parent path is a file, permission denied on an ancestor directory, read-only filesystem, or disk/quota issues.","commonSituations":"serverRootDir points inside a read-only container filesystem or a root-owned directory the process user cannot write; a file exists at the target path; a mounted volume with wrong ownership (common in Docker/K8s deployments).","solutions":["Check permissions on the parent directories of serverRootDir and ensure the process user can create it (chown/chmod or pick a writable location)","Verify no regular file exists at serverRootDir or one of its ancestors (MkdirAll fails with ENOTDIR)","Inspect the wrapped cause after \"uow: creating server root directory: \" to identify the exact OS error (EACCES, ENOTDIR, EROFS, ENOSPC)","If running in a container, mount the data directory as a writable volume"],"exampleFix":"// before (container, read-only path)\n-u BD_SERVER_ROOT=/data\n// after\n-v bd-data:/data (writable volume) and ensure ownership matches the process user: chown 1000:1000 /var/lib/bd-data","handlingStrategy":"validation","validationCode":"if err := os.MkdirAll(serverRootDir, config.BeadsDirPerm); err != nil {\n    return fmt.Errorf(\"pre-check: cannot create server root dir %q: %w\", serverRootDir, err)\n}","typeGuard":"func writableDir(path string) bool {\n    if fi, err := os.Stat(path); err == nil {\n        return fi.IsDir() && unix.Access(path, unix.W_OK) == nil\n    }\n    parent := filepath.Dir(path)\n    return unix.Access(parent, unix.W_OK) == nil\n}","tryCatchPattern":"provider, err := uow.NewExternalDoltServerUOWProvider(ctx, db, root, dir, ext)\nif err != nil {\n    if strings.Contains(err.Error(), \"creating server root directory\") {\n        var pe *fs.PathError\n        if errors.As(err, &pe) {\n            return fmt.Errorf(\"filesystem: cannot create %s (%v); check permissions/ownership\", pe.Path, pe.Err)\n        }\n    }\n    return err\n}","preventionTips":["Provision the server root directory in deployment (IaC/volume mounts) with correct ownership for the process user","Never point serverRootDir at a read-only filesystem or a path containing a regular file","Pre-create the directory during installation and verify writability with a startup health check"],"tags":["filesystem","permissions","uow","dolt","wrapped-error"],"backgroundTag":"permission-denied","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}