gastownhall/beads · error

cannot create shared dolt directory %s: %w

Error message

cannot create shared dolt directory %s: %w

What it means

SharedDoltDir returns ~/.beads/shared-server/dolt/, creating it on first use. It first calls SharedServerDir() (propagating its errors untouched) and then os.MkdirAll on the dolt subdirectory; failure to create that subdirectory is wrapped with this message including the full path.

Source

Thrown at internal/doltserver/doltserver.go:282

	if err != nil {
		return "", err
	}
	if err := os.MkdirAll(dir, config.BeadsDirPerm); err != nil {
		return "", fmt.Errorf("cannot create shared server directory %s: %w", dir, err)
	}
	return dir, nil
}

// SharedDoltDir returns the dolt data directory for the shared server.
// Returns ~/.beads/shared-server/dolt/ (created on first use).
func SharedDoltDir() (string, error) {
	serverDir, err := SharedServerDir()
	if err != nil {
		return "", err
	}
	dir := filepath.Join(serverDir, "dolt")
	if err := os.MkdirAll(dir, config.BeadsDirPerm); err != nil {
		return "", fmt.Errorf("cannot create shared dolt directory %s: %w", dir, err)
	}
	return dir, nil
}

// resolveServerDir returns the canonical server directory for dolt state files.
// In shared server mode, returns ~/.beads/shared-server/ instead of the
// project's .beads/ directory.
func resolveServerDir(beadsDir string) string {
	if IsSharedServerMode() {
		dir, err := SharedServerDir()
		if err != nil {
			fmt.Fprintf(os.Stderr, "Warning: shared server directory unavailable, using per-project mode: %v\n", err)
			return beadsDir
		}
		return dir
	}
	return beadsDir
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Read the wrapped OS error to identify the root cause
  2. Check that ~/.beads/shared-server is a directory and writable
  3. If ~/.beads/shared-server/dolt is a file, remove it so MkdirAll can create the directory
  4. Fix ownership/permissions on the shared-server directory
  5. Free disk space or remount the volume read-write

Example fix

// before: ignoring error
dir, _ := doltserver.SharedDoltDir()
// after: surface the wrapped OS error
dir, err := doltserver.SharedDoltDir()
if err != nil {
    return fmt.Errorf("cannot use shared dolt dir: %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

serverDir, err := doltserver.SharedServerDir()
if err == nil {
    if fi, err := os.Stat(filepath.Join(serverDir, "dolt")); err == nil && !fi.IsDir() {
        return fmt.Errorf("%s/dolt is a file; remove it", serverDir)
    }
}

Type guard

func isSharedDoltDirErr(err error) bool {
    return err != nil && strings.Contains(err.Error(), "cannot create shared dolt directory")
}

Try / catch

dir, err := doltserver.SharedDoltDir()
if err != nil {
    if strings.Contains(err.Error(), "not a directory") || strings.Contains(err.Error(), "permission denied") {
        os.RemoveAll(filepath.Join(serverDirGuess, "dolt")) // careful: only if known-bad
    }
    return err
}

Prevention

When it happens

Trigger: Calling SharedDoltDir() (directly or via ResolveDoltDir/TestSharedDoltDir) when the shared server dir was created but the dolt/ subdir cannot be created — filesystem permission changes between the two calls, a file named dolt inside ~/.beads/shared-server, or ENOSPC/readonly fs.

Common situations: Concurrent provisioning where another process created a dolt file instead of a directory, running bd as different users against the same shared HOME, disk quota exhaustion on the shared server volume.

Related errors


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