gastownhall/beads · error
resolving beads dir %s: %w
Error message
resolving beads dir %s: %w
What it means
ResolvePhysicalRoots wraps filepath.Abs(beadsDir) failures as "resolving beads dir %s: %w". This function canonicalizes the beads directory into absolute physical roots used for gate-file planning; it throws when the OS cannot convert the given beads dir path to an absolute path — rare, and usually caused by extremely long paths (Windows MAX_PATH) or malformed input (empty string leading to getwd failure).
Source
Thrown at internal/doltserver/physical_root.go:250
// (internal/storage/embeddeddolt), which is precisely where
// ResolveDoltDir is wrong (it reports beadsDir/dolt) and why this
// function does not reuse it wholesale.
// 5. no metadata.json: after the shared-server rescue, mirror the open
// path's discovery fallback (internal/beads findDatabaseInBeadsDir):
// an embeddeddolt/ dir means embedded, else a dolt/ dir means a
// server-layout workspace, else default to the embedded root (which
// may not exist yet — gating a not-yet-existing root is fine, the gate
// file lives beside it and workspacegate only requires the PARENT to
// exist). The CLI's nil-config branch honors no other env rescue.
//
// Roots are returned absolute. Symlink canonicalization is deliberately NOT
// performed here: workspacegate.ForPhysicalRoot canonicalizes the gate
// file's parent itself (and refuses symlinked roots), and resolving here too
// would double-handle and could disagree with the gate's own rules.
func ResolvePhysicalRoots(beadsDir string) (PhysicalRoots, error) {
abs, err := filepath.Abs(beadsDir)
if err != nil {
return PhysicalRoots{}, fmt.Errorf("resolving beads dir %s: %w", beadsDir, err)
}
abs = filepath.Clean(abs)
pr := PhysicalRoots{BeadsDir: abs}
// Side-effect-free config load: never trigger the legacy config.json
// migration. Absent metadata.json is treated as cfg == nil.
var cfg *configfile.Config
if _, statErr := os.Stat(configfile.ConfigPath(abs)); statErr == nil {
loaded, loadErr := configfile.Load(abs)
if loadErr != nil {
// A present-but-broken metadata.json is authoritative: the open
// path refuses to fall back, so gate planning refuses to guess.
return PhysicalRoots{}, fmt.Errorf("loading config for gate resolution: %w", loadErr)
}
cfg = loaded
}
addRoot := func(root string) error {View on GitHub (pinned to 71377f2769)
Solutions
- cd to a valid existing directory before running bd, or pass an explicit --repo/path flag.
- Shorten the path (move the workspace closer to the drive root) or enable Windows long paths (LongPathsEnabled registry / git config core.longpaths).
- Ensure the beads dir argument passed to ResolvePhysicalRoots is non-empty and well-formed.
- Re-create the deleted working directory or restart the shell so getwd returns a valid path.
Example fix
// before
ResolvePhysicalRoots("") // cwd deleted -> getwd error
// after
abs, _ := filepath.EvalSymlinks(beadsDir)
ResolvePhysicalRoots(abs) // e.g. "/home/u/proj/.beads" Defensive patterns
Strategy: validation
Validate before calling
if beadsDir == "" {
return fmt.Errorf("beadsDir must not be empty")
}
if cwd, err := os.Getwd(); err != nil {
return fmt.Errorf("current directory unavailable (%v); cd to a valid dir", err)
} else if filepath.IsLocal(beadsDir) {
if _, err := os.Stat(filepath.Join(cwd, beadsDir)); err != nil {
return fmt.Errorf("beads dir %s not found", beadsDir)
}
} Type guard
func resolvablePath(p string) bool {
if p == "" { return false }
if filepath.IsAbs(p) { _, err := os.Stat(p); return err == nil }
_, err := os.Getwd()
return err == nil
} Try / catch
roots, err := ResolvePhysicalRoots(beadsDir)
if err != nil {
if strings.Contains(err.Error(), "resolving beads dir") {
return fmt.Errorf("bad --repo path %q or invalid cwd; pass an absolute path", beadsDir)
}
return err
} Prevention
- Pass absolute paths for the beads dir instead of relying on cwd
- Restart the shell if the working directory was deleted/renamed
- Enable Windows long paths for deep workspaces
- Validate beadsDir existence before calling ResolvePhysicalRoots
When it happens
Trigger: ResolvePhysicalRoots is called (directly or by tests/startup) with a beadsDir for which filepath.Abs fails: empty string while the current working directory is unavailable (deleted cwd), or a path exceeding OS length limits.
Common situations: Running bd from a directory that was deleted or renamed while the shell sits in it (getwd fails); Windows paths beyond 260 chars without long-path support enabled; passing "" as beadsDir programmatically.
Related errors
- resolving physical root %s: %w
- multiple .doltcfg directories detected
- resolve path: %w
- no .beads directory found
- beadsDir must not be empty
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/73c79975eee2853f.
Report an issue: GitHub.