{"record":{"id":"b752028699fe50c5","repo":"gastownhall/beads","slug":"opening-log-file-w","errorCode":null,"errorMessage":"opening log file: %w","messagePattern":"opening log file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/doltserver/doltserver.go","lineNumber":1347,"sourceCode":"\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)\n\t\t\tif reclaimErr != nil {\n\t\t\t\t_ = logFile.Close()\n\t\t\t\treturn nil, fmt.Errorf(\"cannot start dolt server on port %d: %w\", actualPort, reclaimErr)\n\t\t\t}\n\t\t\tif adoptPID > 0 {\n\t\t\t\t_ = logFile.Close()\n\t\t\t\t_ = os.WriteFile(pidPath(beadsDir), []byte(strconv.Itoa(adoptPID)), 0600)","sourceCodeStart":1329,"sourceCodeEnd":1365,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/doltserver/doltserver.go#L1329-L1365","documentation":"Start() opens (creating if needed) the dolt server log file at logPath(beadsDir) with mode 0600 before launching the child process. If os.OpenFile fails, the error is wrapped as 'opening log file'. The server refuses to start without a log sink because diagnostics for later failures (e.g. GH#3290) depend on it.","triggerScenarios":"os.OpenFile(logPath(beadsDir), O_CREATE|O_APPEND|O_WRONLY, 0600) fails: unwritable directory, path is a directory, or too many open files.","commonSituations":"Beads dir permissions wrong after a user/uid change; disk full; logPath colliding with a directory of the same name; EMFILE under heavy fd usage in long-lived processes.","solutions":["Check permissions/ownership of the beads data directory and fix with chown/chmod.","Verify no file/directory with the log file's name blocks creation.","Free disk space or inodes if the volume is full.","Check ulimit -n (open file limit) if EMFILE is reported and close leaked descriptors."],"exampleFix":"// before\nls -l ~/.beads/logs\n// after\nchmod u+w ~/.beads ~/.beads/logs\n# or clear space: df -h ~/.beads","handlingStrategy":"validation","validationCode":"const logFile = path.join(dataDir, 'dolt.log');\ntry { await fs.appendFile(logFile, ''); } // probes create+write\ncatch { throw new Error(`Cannot write dolt log at ${logFile}; fix permissions/disk`); }","typeGuard":"null","tryCatchPattern":"try {\n  await bdStart();\n} catch (e) {\n  if (/opening log file/.test(e.message)) {\n    // inspect errno: EACCES -> permissions, ENOSPC -> disk, EMFILE -> fd limit\n  }\n  throw e;\n}","preventionTips":["Keep the beads dir writable by the running user.","Watch disk space/inode usage.","Raise ulimit -n for long-lived daemons.","Don't create files/dirs that collide with the log path."],"tags":["filesystem","logging","startup"],"backgroundTag":"log-file-open-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}