gastownhall/beads · error

%w The Dolt database is locked.%s Try: bd doctor --fix (cle

Error message

%w

The Dolt database is locked.%s
Try: bd doctor --fix (clears stale locks), or kill the holding process.

What it means

wrapLockError detects that a database error was caused by the Dolt database being locked and augments it with an actionable message: the original error, an optional hint identifying the holding process, and the recommended remediation (bd doctor --fix to clear stale locks, or kill the holder).

Source

Thrown at internal/storage/dolt/store.go:702

func isLockError(err error) bool {
	if err == nil {
		return false
	}
	errStr := strings.ToLower(err.Error())
	return strings.Contains(errStr, "database is locked") ||
		strings.Contains(errStr, "lock file") ||
		strings.Contains(errStr, "noms lock") ||
		strings.Contains(errStr, "locked by another dolt process")
}

// wrapLockError wraps lock-related errors with actionable guidance.
// Non-lock errors and nil are returned unchanged.
func wrapLockError(err error) error {
	if !isLockError(err) {
		return err
	}
	hint := lockProcessHint()
	return fmt.Errorf("%w\n\nThe Dolt database is locked.%s\n"+
		"Try: bd doctor --fix (clears stale locks), or kill the holding process.", err, hint)
}

// lockProcessHint tries to identify the process holding the database lock.
// Returns a hint string like " Process 12345 (bd) may be holding the lock."
// Returns empty string if identification fails or on unsupported platforms.
func lockProcessHint() string {
	// Look for other bd/dolt processes that might hold the lock
	entries, err := os.ReadDir("/proc")
	if err != nil {
		// /proc not available (macOS, Windows, FreeBSD) — skip PID detection
		return ""
	}

	myPID := os.Getpid()
	var holders []string
	for _, entry := range entries {
		if !entry.IsDir() {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Run bd doctor --fix to clear stale Dolt locks.
  2. Identify and terminate the holding process (see the 'Process NNNN' hint appended to the error).
  3. Avoid running multiple bd processes against the same database concurrently; retry after the other finishes.

Example fix

// before
$ bd update bd-1 --status closed
# fails: database is locked
// after
$ bd doctor --fix
$ bd update bd-1 --status closed
Defensive patterns

Strategy: retry

Validate before calling

// check for a stale Dolt lock before writing
if _, err := os.Stat(filepath.Join(repoPath, ".dolt", "locks")); err == nil {
	// entries present: another process may hold the lock
}

Type guard

func isLockError(err error) bool {
	return err != nil && strings.Contains(strings.ToLower(err.Error()), "lock")
}

Try / catch

if err := store.SlotClear(ctx, id, key, actor); err != nil {
	if isLockError(err) {
		// hint: run bd doctor --fix, or kill the holding process, then retry
	}
	return err
}

Prevention

When it happens

Trigger: Any SQL operation while another process (or a crashed prior process' leftover lock file) holds the Dolt database lock — concurrent bd commands, an editor session, or a stale .lock file after a crash.

Common situations: Running two bd commands simultaneously on the same repo; a previous bd process was SIGKILLed leaving stale locks; a background sync/daemon holds the lock during your command.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/d43de824205bc28b. Report an issue: GitHub.