{"record":{"id":"a95a3d1e69e1ca1c","repo":"gastownhall/beads","slug":"resolving-doltcfg-directory-w","errorCode":null,"errorMessage":"resolving .doltcfg directory: %w","messagePattern":"resolving \\.doltcfg directory: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/doltserver/doltserver.go","lineNumber":1340,"sourceCode":"\t\t// Ensure dolt database directory is initialized\n\t\tif err := ensureDoltInit(doltDir); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"initializing dolt database: %w\", err)\n\t\t}\n\n\t\t// Rotate the log if it has grown past the configured ceiling. This is a\n\t\t// startup-only check — dolt owns the fd directly once launched, so we can\n\t\t// only intervene between runs. See logrotate.go for the caveat discussion.\n\t\tmaybeRotateLog(beadsDir)\n\n\t\t// Resolve .doltcfg once, before the port retry loop — it does not\n\t\t// depend on the port, and an ambiguous both-exist result must fail\n\t\t// Start() outright rather than retry into a fresh unintended\n\t\t// $data_dir/.doltcfg (see resolveCfgDir).\n\t\tvar cfgDir string\n\t\tif useArchiveLevelConfig {\n\t\t\tcfgDir, err = resolveCfgDir(doltDir)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"resolving .doltcfg directory: %w\", err)\n\t\t\t}\n\t\t}\n\n\t\t// Open log file\n\t\tlogFile, err := os.OpenFile(logPath(beadsDir), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600) //nolint:gosec // G304: logPath derives from user-configured beadsDir\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"opening log file: %w\", err)\n\t\t}\n\n\t\t// Resolve the port to use. Explicit ports (env/config) go through\n\t\t// reclaimPort for conflict detection. Port 0 means ephemeral — allocate\n\t\t// a fresh port from the OS with retry for TOCTOU races.\n\t\tactualPort = cfg.Port\n\t\texplicitPort := actualPort > 0\n\n\t\tif explicitPort {\n\t\t\t// Explicit port: check for conflicts and adopt existing servers.\n\t\t\tadoptPID, reclaimErr := reclaimPort(cfg.Host, actualPort, beadsDir)","sourceCodeStart":1322,"sourceCodeEnd":1358,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/doltserver/doltserver.go#L1322-L1358","documentation":"Start() wraps failures from resolveCfgDir(), which locates or creates the .doltcfg directory the managed dolt sql-server will use. When useArchiveLevelConfig is set, Start resolves the config dir before spawning the server; any filesystem-level failure there is wrapped as 'resolving .doltcfg directory'. The design avoids silently retrying into a fresh unintended $data_dir/.doltcfg when an existing one is unusable.","triggerScenarios":"Calling Start (via EnsureRunningDetailed) with archive-level config enabled when resolveCfgDir cannot resolve doltDir: the path cannot be created (permissions, read-only fs) or stat fails on an existing .doltcfg.","commonSituations":"Beads dir owned by root after running with sudo; read-only or full disk; NFS/network mount with permission issues; misconfigured beadsDir pointing at an unwritable path.","solutions":["Check permissions on the .doltcfg directory inside the data dir and correct ownership (chown -R $USER).","Verify the beads data directory exists, is writable, and is on a writable filesystem (not read-only mount).","Free disk space if the filesystem is full.","Set an explicit, valid beadsDir via env/config and retry bd."],"exampleFix":"// before: data dir owned by root, bd runs as user\n$ bd start\n// error: resolving .doltcfg directory: mkdir ...: permission denied\n// after\n$ sudo chown -R \"$USER\" ~/.beads\n$ bd start","handlingStrategy":"validation","validationCode":"// before starting\nconst dataDir = process.env.BD_DIR || path.join(os.homedir(), '.beads');\nconst cfgDir = path.join(dataDir, '.doltcfg');\nawait fs.mkdir(cfgDir, { recursive: true });\nawait fs.access(cfgDir, fs.constants.W_OK); // throws early if unwritable","typeGuard":"null","tryCatchPattern":"try {\n  await bdStart();\n} catch (e) {\n  if (/resolving \\.doltcfg directory/.test(e.message)) {\n    console.error('Fix permissions on', dataDir, ':', e.cause);\n  }\n  throw e;\n}","preventionTips":["Never run bd with sudo; fix ownership instead.","Keep the beads dir on a local writable filesystem, not read-only NFS.","Monitor free disk space where the data dir lives.","Use an absolute, stable beadsDir path in config."],"tags":["filesystem","config","startup"],"backgroundTag":"config-dir-unwritable","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}