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
- Inspect what .dolt is: `ls -ld <doltDir>/.dolt; file <doltDir>/.dolt`.
- 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).
- If it should have been a directory, restore the real .dolt directory from a backup or re-clone/re-init the Dolt database.
- Check sync-tool conflict copies (e.g. `.dolt (conflicted copy)`) and resolve them, then verify with `dolt status` inside doltDir.
- 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
- Exclude .beads/dolt from cloud-sync tools (Dropbox/OneDrive) that create conflict files.
- Restore archives with proper tooling (tar with -p into the right location) and verify .dolt is a directory afterward.
- Don't redirect shell output into paths named .dolt (`> .dolt`).
- Verify with `file .dolt` after any manual copying of repository data.
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
- remote target %s is non-empty but is neither a bare git repo
- backup destination does not exist: %w
- backup destination is not a directory: %s
- multiple .doltcfg directories detected
- dolt path is not executable
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/96f23133bfdb1461.
Report an issue: GitHub.