{"record":{"id":"d3b6df675d3ebff7","repo":"gastownhall/beads","slug":"checking-dolt-compatibility-marker-s-w","errorCode":null,"errorMessage":"checking dolt compatibility marker %s: %w","messagePattern":"checking dolt compatibility marker (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/doltserver/doltserver.go","lineNumber":1918,"sourceCode":"// 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 {\n\t\treturn fmt.Errorf(\"creating dolt directory: %w\", err)\n\t}\n\n\tdotDolt := filepath.Join(doltDir, \".dolt\")\n\n\tif _, err := os.Stat(dotDolt); err == nil {","sourceCodeStart":1900,"sourceCodeEnd":1936,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/doltserver/doltserver.go#L1900-L1936","documentation":"MarkDoltDirCompatible stats the compatibility marker <doltDir>/.bd-dolt-ok after confirming .dolt exists (internal/doltserver/doltserver.go:1918). If the marker is absent it is written; if os.Stat fails for a reason other than NotExist (permission denied, EIO, etc.) this error is returned. It is NOT the 'pre-0.56 incompatible database' case — that case returns a separate incompatibility error, not this one. The wrapped *PathError pinpoints why the marker path could not be examined.","triggerScenarios":"os.Stat on <doltDir>/.bd-dolt-ok fails with something other than ENOENT while MarkDoltDirCompatible runs from bd server/repair paths: no write/search permission on doltDir, immutable file attribute, failing disk (EIO), or a security policy (e.g. sandbox denying stat on dotfiles).","commonSituations":"dolt dir owned by another user after running bd with sudo once; chattr +i applied to the marker by an overzealous hardening script; failing SSD returning I/O errors; AppArmor/SELinux denials on the bd binary accessing the profile directory.","solutions":["Read the wrapped os.PathError — the errno (permission denied vs I/O error) tells you which branch to take.","Fix ownership/permissions: `ls -ld <doltDir>` and `chown -R $USER <doltDir>` or `chmod u+rwx <doltDir>` if a prior sudo run claimed it.","Check for immutable flags: `lsattr <doltDir>/.bd-dolt-ok` and `chattr -i` if set.","If dmesg/filesystem logs show I/O errors, back up the data and check disk health (`smartctl`) before proceeding.","Check audit logs for SELinux/AppArmor denials and adjust policy or move the data dir to an allowed path."],"exampleFix":"// before: earlier sudo run left the dir root-owned\n$ ls -ld ~/.beads/dolt\ndrwx------ 2 root root ... .beads/dolt\n// after\n$ sudo chown -R $USER:$USER ~/.beads/dolt\n$ bd ready   # marker check succeeds","handlingStrategy":"validation","validationCode":"// Verify the marker path is examinable before running bd\nimport (\"os\"; \"path/filepath\")\nfunc markerAccessible(doltDir string) error {\n    if _, err := os.Stat(filepath.Join(doltDir, \".bd-dolt-ok\")); err != nil {\n        if os.IsNotExist(err) { return nil } // absent is fine; bd will create it\n        return err\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"// Go: unwrap the PathError to classify the failure\nif err := MarkDoltDirCompatible(dir); err != nil && strings.HasPrefix(err.Error(), \"checking dolt compatibility marker\") {\n    var perr *os.PathError\n    if errors.As(err, &perr) {\n        switch {\n        case errors.Is(perr.Err, syscall.EACCES):\n            return fmt.Errorf(\"chmod/chown %s for the current user\", dir)\n        case errors.Is(perr.Err, syscall.EIO):\n            return fmt.Errorf(\"disk I/O error on %s — check storage health\", dir)\n        }\n    }\n    return err\n}","preventionTips":["Never run bd with sudo; if you did, chown ~/.beads back to your user.","Don't set immutable flags (chattr +i) on files inside the bd data directory.","Monitor disk health on machines hosting Dolt data; investigate EIO in dmesg promptly.","Keep the data directory on local, non-synced storage with stable permissions."],"tags":["dolt","filesystem","permissions","stat"],"backgroundTag":"filesystem-permission-denied","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}