{"record":{"id":"96f23133bfdb1461","repo":"gastownhall/beads","slug":"dolt-metadata-path-s-is-not-a-directory","errorCode":null,"errorMessage":"dolt metadata path %s is not a directory","messagePattern":"dolt metadata path (.+?) is not a directory","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/doltserver/doltserver.go","lineNumber":1912,"sourceCode":"// the database was created by a pre-0.56 bd version (which used embedded mode).\n// Those databases are incompatible with the current server-only architecture.\nconst bdDoltMarker = \".bd-dolt-ok\"\n\n// MarkDoltDirCompatible writes the canonical bd compatibility marker when\n// doltDir contains a local Dolt repository. It no-ops when there is no .dolt/\n// directory, which lets server and repair paths call it defensively.\nfunc MarkDoltDirCompatible(doltDir string) error {\n\tif doltDir == \"\" {\n\t\treturn errors.New(\"dolt directory is required\")\n\t}\n\tdotDolt := filepath.Join(doltDir, \".dolt\")\n\tif info, err := os.Stat(dotDolt); err != nil {\n\t\tif os.IsNotExist(err) {\n\t\t\treturn nil\n\t\t}\n\t\treturn fmt.Errorf(\"checking dolt metadata directory %s: %w\", dotDolt, err)\n\t} else if !info.IsDir() {\n\t\treturn fmt.Errorf(\"dolt metadata path %s is not a directory\", dotDolt)\n\t}\n\tmarkerPath := filepath.Join(doltDir, bdDoltMarker)\n\tif _, err := os.Stat(markerPath); err == nil {\n\t\treturn nil\n\t} else if !os.IsNotExist(err) {\n\t\treturn fmt.Errorf(\"checking dolt compatibility marker %s: %w\", markerPath, err)\n\t}\n\tif err := os.WriteFile(markerPath, []byte(\"ok\\n\"), 0600); err != nil {\n\t\treturn fmt.Errorf(\"writing dolt compatibility marker %s: %w\", markerPath, err)\n\t}\n\treturn nil\n}\n\n// ensureDoltInit initializes a dolt database directory if .dolt/ doesn't exist.\n// If .dolt/ exists, seeds the .bd-dolt-ok marker for existing working databases.\n// See GH#2137 for background on pre-0.56 database compatibility.\nfunc ensureDoltInit(doltDir string) error {\n\tif err := os.MkdirAll(doltDir, config.BeadsDirPerm); err != nil {","sourceCodeStart":1894,"sourceCodeEnd":1930,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/doltserver/doltserver.go#L1894-L1930","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: archive extraction created a file where the repo dir should be\n$ ls -ld .beads/dolt/.dolt\n-rw-r--r-- 1 me me 0 ... .dolt\n// after\n$ rm -f .beads/dolt/.dolt\n$ bd doctor   # re-initializes the local Dolt repository","handlingStrategy":"validation","validationCode":"// Detect a non-directory .dolt before bd touches it\nimport (\"os\"; \"path/filepath\")\nfunc doltMetaIsDir(doltDir string) (ok bool, err error) {\n    fi, err := os.Stat(filepath.Join(doltDir, \".dolt\"))\n    if os.IsNotExist(err) { return true, nil } // no repo: fine\n    if err != nil { return false, err }\n    return fi.IsDir(), nil // false means the error will fire\n}","typeGuard":null,"tryCatchPattern":"// Go: intercept and guide remediation\nif err := MarkDoltDirCompatible(dir); err != nil && strings.Contains(err.Error(), \"is not a directory\") {\n    return fmt.Errorf(\"%w — remove or restore the stray .dolt entry, then re-run bd doctor\", err)\n}","preventionTips":["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."],"tags":["dolt","filesystem","corrupt-repo","validation"],"backgroundTag":"dolt-repo-corrupt","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}