gastownhall/beads · error
failed to start dolt server after %d attempts: %w Check logs
Error message
failed to start dolt server after %d attempts: %w Check logs: %s
What it means
The generic failure path when all dolt sql-server start attempts are exhausted and no corrupt manifest was detected. It wraps the last attempt's error (lastErr) and points at the server log file. This is what users see when the specific GH#3290 corruption branch does not apply.
Source
Thrown at internal/doltserver/doltserver.go:1475
break
}
lastErr = nil
break
}
_ = logFile.Close()
if lastErr != nil {
// GH#3290 / bd-6dnrw.6: unclean-shutdown manifest corruption is
// detected here but never auto-repaired — reinitializing .dolt is
// destructive, so repair stays behind explicit bd doctor --fix.
if dirs, detErr := detectCorruptManifest(beadsDir, doltDir); detErr == nil && len(dirs) > 0 {
return nil, fmt.Errorf("failed to start dolt server after %d attempts: %w\n"+
"Corrupt manifest with no recoverable data detected (GH#3290) in:\n %s\n"+
"Run 'bd doctor --fix' to back up the corrupt database(s) and reinitialize.\nCheck logs: %s",
attempts, lastErr, strings.Join(dirs, "\n "), logPath(beadsDir))
}
return nil, fmt.Errorf("failed to start dolt server after %d attempts: %w\nCheck logs: %s",
attempts, lastErr, logPath(beadsDir))
}
}
// Write PID and port files
if err := os.WriteFile(pidPath(beadsDir), []byte(strconv.Itoa(pid)), 0600); err != nil {
if proc, findErr := os.FindProcess(pid); findErr == nil {
_ = proc.Kill()
}
return nil, fmt.Errorf("writing PID file: %w", err)
}
if err := writePortFile(beadsDir, actualPort); err != nil {
if proc, findErr := os.FindProcess(pid); findErr == nil {
_ = proc.Kill()
}
_ = os.Remove(pidPath(beadsDir))
return nil, fmt.Errorf("writing port file: %w", err)
}View on GitHub (pinned to 71377f2769)
Solutions
- Read the referenced log file (last line of the error) for the child's real failure.
- Resolve the underlying issue from lastErr: free the port, fix config, or verify the dolt binary runs (dolt version).
- Try an ephemeral port (port 0) to rule out port conflicts.
- Check system resources: ulimits, memory, and that the host address is valid on this machine.
Example fix
// before: bind to a nonexistent host IP BD_HOST=10.0.0.99 bd start # attempts exhausted // after BD_HOST=127.0.0.1 bd start # or unset to use default
Defensive patterns
Strategy: try-catch
Validate before calling
// sanity checks before starting
await fs.access(path.join(dataDir, '.dolt'), fs.constants.W_OK);
await execFile('dolt', ['version']); // dolt binary works
const hostIfaces = Object.keys(os.networkInterfaces());
if (cfgHost && !hostIfaces.includes(cfgHost) && cfgHost !== 'localhost' && cfgHost !== '127.0.0.1')
console.warn('configured host not present on this machine'); Type guard
null
Try / catch
try {
await bdStart();
} catch (e) {
const m = /failed to start dolt server after (\d+) attempts/.exec(e.message);
if (m && !/Corrupt manifest/.test(e.message)) {
const logTail = await readTail(logFile); // log path is in the error
// act on logTail: port conflict, bad config, resource limits
}
throw e;
} Prevention
- Always read the referenced log file first — it names the real cause.
- Validate configured host/port values before start.
- Keep the dolt binary on PATH and up to date.
- Check ulimits and memory on constrained hosts.
When it happens
Trigger: Every attempt failed (bind conflicts, immediate exits, config issues) and detectCorruptManifest found nothing — e.g. port held by a foreign process across all retries.
Common situations: Persistent port conflict; repeated spawn failures due to a broken dolt binary or PATH; resource limits (fork failures); misconfigured host binding (e.g. bad interface address).
Related errors
- dolt sql-server exited immediately on port %d (attempt %d/%d
- start database server: %w
- multiple .doltcfg directories detected
- pidfile: invalid pid
- ErrUnverifiableProcess
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/0bb10ea38c66a893.
Report an issue: GitHub.