gastownhall/beads · error

dolt metadata path %s is not a directory

Error message

dolt metadata path %s is not a directory

What it means

MarkDoltDirCompatible requires that <doltDir>/.dolt, when it exists, is actually a directory (internal/doltserver/doltserver.go:1912). If os.Stat succeeds but info.IsDir() is false — .dolt is a regular file, symlink to a file, socket, etc. — bd refuses to proceed rather than writing its marker next to an invalid repository layout. This guards the pre-0.56 embedded-database compatibility check, which only makes sense for real .dolt metadata directories.

Source

Thrown at internal/doltserver/doltserver.go:1912

// the database was created by a pre-0.56 bd version (which used embedded mode).
// Those databases are incompatible with the current server-only architecture.
const bdDoltMarker = ".bd-dolt-ok"

// MarkDoltDirCompatible writes the canonical bd compatibility marker when
// doltDir contains a local Dolt repository. It no-ops when there is no .dolt/
// directory, which lets server and repair paths call it defensively.
func MarkDoltDirCompatible(doltDir string) error {
	if doltDir == "" {
		return errors.New("dolt directory is required")
	}
	dotDolt := filepath.Join(doltDir, ".dolt")
	if info, err := os.Stat(dotDolt); err != nil {
		if os.IsNotExist(err) {
			return nil
		}
		return fmt.Errorf("checking dolt metadata directory %s: %w", dotDolt, err)
	} else if !info.IsDir() {
		return fmt.Errorf("dolt metadata path %s is not a directory", dotDolt)
	}
	markerPath := filepath.Join(doltDir, bdDoltMarker)
	if _, err := os.Stat(markerPath); err == nil {
		return nil
	} else if !os.IsNotExist(err) {
		return fmt.Errorf("checking dolt compatibility marker %s: %w", markerPath, err)
	}
	if err := os.WriteFile(markerPath, []byte("ok\n"), 0600); err != nil {
		return fmt.Errorf("writing dolt compatibility marker %s: %w", markerPath, err)
	}
	return nil
}

// ensureDoltInit initializes a dolt database directory if .dolt/ doesn't exist.
// If .dolt/ exists, seeds the .bd-dolt-ok marker for existing working databases.
// See GH#2137 for background on pre-0.56 database compatibility.
func ensureDoltInit(doltDir string) error {
	if err := os.MkdirAll(doltDir, config.BeadsDirPerm); err != nil {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect what .dolt is: `ls -ld <doltDir>/.dolt; file <doltDir>/.dolt`.
  2. If it is a stray file/symlink (not a real Dolt repo), remove it: `rm -f <doltDir>/.dolt`, then let bd re-initialize (`bd doctor` or re-run your bd command).
  3. If it should have been a directory, restore the real .dolt directory from a backup or re-clone/re-init the Dolt database.
  4. Check sync-tool conflict copies (e.g. `.dolt (conflicted copy)`) and resolve them, then verify with `dolt status` inside doltDir.
  5. Keep the Dolt data dir out of cloud-synced folders to prevent recurrence.

Example fix

// before: archive extraction created a file where the repo dir should be
$ ls -ld .beads/dolt/.dolt
-rw-r--r-- 1 me me 0 ... .dolt
// after
$ rm -f .beads/dolt/.dolt
$ bd doctor   # re-initializes the local Dolt repository
Defensive patterns

Strategy: validation

Validate before calling

// Detect a non-directory .dolt before bd touches it
import ("os"; "path/filepath")
func doltMetaIsDir(doltDir string) (ok bool, err error) {
    fi, err := os.Stat(filepath.Join(doltDir, ".dolt"))
    if os.IsNotExist(err) { return true, nil } // no repo: fine
    if err != nil { return false, err }
    return fi.IsDir(), nil // false means the error will fire
}

Try / catch

// Go: intercept and guide remediation
if err := MarkDoltDirCompatible(dir); err != nil && strings.Contains(err.Error(), "is not a directory") {
    return fmt.Errorf("%w — remove or restore the stray .dolt entry, then re-run bd doctor", err)
}

Prevention

When it happens

Trigger: A .dolt entry that is not a directory exists inside the dolt dir when MarkDoltDirCompatible runs: a stray file named .dolt (bad archive extraction, typo'd redirect like `dolt ... > .dolt`), a symlink to a regular file, or a case-collision artifact from a filesystem sync tool.

Common situations: Restoring ~/.beads/dolt from a mis-created tarball; OneDrive/Dropbox/sync conflicts turning .dolt into a file; a user manually poking at the directory; interrupted tooling writing a temp file at that path.

Related errors


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