gastownhall/beads · critical
backing up corrupt dolt database at %s: %w
Error message
backing up corrupt dolt database at %s: %w
What it means
recoverCorruptManifest wraps os.Rename(dotDolt, backupPath) failures as "backing up corrupt dolt database at %s: %w". When bd detects a corrupt dolt manifest, it moves the entire .dolt directory aside (timestamped .corrupt.backup) before re-initializing; this error means the corrupt database could not be preserved, so recovery aborts rather than destroying data.
Source
Thrown at internal/doltserver/manifest_recovery.go:237
func recoverCorruptManifest(beadsDir, doltDir string) ([]string, error) {
nomsDirs, err := detectCorruptManifest(beadsDir, doltDir)
if err != nil {
return nil, err
}
if len(nomsDirs) == 0 {
return nil, nil
}
ts := time.Now().UTC().Format("20060102T150405Z")
var backups []string
for _, nomsDir := range nomsDirs {
dotDolt := filepath.Dir(nomsDir) // .../X/.dolt
dbDir := filepath.Dir(dotDolt) // .../X
backupPath := dotDolt + "." + ts + ".corrupt.backup"
if err := os.Rename(dotDolt, backupPath); err != nil {
return backups, fmt.Errorf("backing up corrupt dolt database at %s: %w", dotDolt, err)
}
backups = append(backups, backupPath)
if err := ensureDoltInit(dbDir); err != nil {
// Best-effort restore so the user is no worse off than before.
_ = os.RemoveAll(dotDolt)
_ = os.Rename(backupPath, dotDolt)
return backups[:len(backups)-1], fmt.Errorf("reinitializing dolt database at %s: %w", dbDir, err)
}
}
return backups, nil
}
View on GitHub (pinned to 71377f2769)
Solutions
- Stop all other dolt/bd processes using the workspace (check with lsof +D .dolt or handle.exe), then retry.
- Fix ownership/permissions so the bd user can rename the .dolt directory.
- Manually back up: cp -r X/.dolt X/.dolt.manual-backup, then remove the corrupt .dolt and let bd re-init.
- Check the filesystem/mount health if rename fails with I/O errors.
Example fix
// before (shell) $ bd start # fails: backing up corrupt dolt database ... $ lsof +D myrepo/.dolt # find the holder $ kill <pid> # stop the stale server // after $ bd start # recovery proceeds: .dolt moved to .dolt.<ts>.corrupt.backup
Defensive patterns
Strategy: validation
Validate before calling
// before attempting recovery, ensure nothing holds .dolt open
out, _ := exec.Command("lsof", "+D", dotDolt).Output()
if len(bytes.TrimSpace(out)) > 0 {
return fmt.Errorf(".dolt in use; stop other processes first")
}
if info, err := os.Stat(dotDolt); err != nil || !info.IsDir() {
return fmt.Errorf(".dolt missing or not a directory")
} Try / catch
backups, err := RecoverCorruptManifest(ws)
if err != nil {
var pe *fs.PathError
if errors.As(err, &pe) && errors.Is(pe.Err, syscall.EBUSY) {
return fmt.Errorf("another process holds .dolt open; stop it and retry: %w", err)
}
return err
} Prevention
- Stop all bd/dolt processes on the workspace before recovery
- On Windows, ensure no handles are open in .dolt (open files cannot be renamed)
- Keep .dolt and its backup target on the same filesystem
- Run bd as a user with write permission on the workspace
When it happens
Trigger: A corrupt manifest signature is detected during server start, recoverCorruptManifest tries to rename the .dolt directory to .dolt.<ts>.corrupt.backup, and the rename fails: files inside are open/locked (another server or process holds them), permission problems, or cross-device paths.
Common situations: A second bd/dolt process is still running against the same workspace holding open file handles (especially on Windows where open files cannot be renamed); bd runs unprivileged while .dolt is root-owned; the workspace is on a network mount with locking issues.
Related errors
- failed to rename temp file: %w
- failed to migrate database %s to %s: %w
- retiring sidecar %s -> %s: %w
- atomicfile: rename: %w
- failed to start dolt server after %d attempts: %w Corrupt ma
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/b43381fd2eaa37f9.
Report an issue: GitHub.