gastownhall/beads · error

resolving physical root %s: %w

Error message

resolving physical root %s: %w

What it means

Inside ResolvePhysicalRoots, the addRoot helper wraps filepath.Abs(root) failures as "resolving physical root %s: %w". Each configured physical root (from metadata or env overrides) must be converted to an absolute, cleaned path before being added to PhysicalRoots.Roots; this error means one of those configured root strings could not be resolved — typically because the cwd is invalid or the root string is empty/malformed.

Source

Thrown at internal/doltserver/physical_root.go:271

	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 {
		rootAbs, aerr := filepath.Abs(root)
		if aerr != nil {
			return fmt.Errorf("resolving physical root %s: %w", root, aerr)
		}
		pr.Roots = append(pr.Roots, filepath.Clean(rootAbs))
		return nil
	}

	switch {
	case cfg != nil && cfg.IsDoltProxiedServerMode():
		pr.Mode = "proxied-server"
		root, perr := ResolveProxiedServerRootPath(abs)
		if perr != nil {
			return PhysicalRoots{}, fmt.Errorf("resolving proxied-server root: %w", perr)
		}
		pr.Provenance = fmt.Sprintf("metadata.json dolt_mode=proxied-server; root %s via env/client-info/default", root)
		if err := addRoot(root); err != nil {
			return PhysicalRoots{}, err
		}

	case IsSharedServerMode():

View on GitHub (pinned to 71377f2769)

Solutions

  1. Fix the offending root value in .beads/metadata.json (or the env override) — it must be a non-empty relative or absolute path.
  2. Run bd from a valid existing directory, or pass absolute paths in configuration.
  3. Shorten paths or enable Windows long-path support if path length is the cause.
  4. Run bd doctor to validate metadata before starting the server.

Example fix

// before
{"roots": [""]}   // empty root -> Abs("") -> getwd error
// after
{"roots": ["/home/u/proj"]}
Defensive patterns

Strategy: validation

Validate before calling

for _, root := range cfgRoots {
    if strings.TrimSpace(root) == "" {
        return fmt.Errorf("physical root entry is empty; fix metadata/env override")
    }
}
if _, err := os.Getwd(); err != nil {
    return fmt.Errorf("cwd invalid; use absolute root paths")
}

Type guard

func rootResolvable(root string) bool {
    if strings.TrimSpace(root) == "" { return false }
    if filepath.IsAbs(root) { return true }
    _, err := os.Getwd()
    return err == nil
}

Try / catch

roots, err := ResolvePhysicalRoots(beadsDir)
if err != nil {
    if strings.Contains(err.Error(), "resolving physical root") {
        return fmt.Errorf("a configured root is unresolvable; check metadata.json roots and env overrides")
    }
    return err
}

Prevention

When it happens

Trigger: A root entry from metadata.json or server-mode env overrides is an empty string (Abs falls back to getwd, which fails if cwd is gone) or a path exceeding OS limits; ResolvePhysicalRoots is invoked during startup or tests with such configuration.

Common situations: metadata.json contains an empty or whitespace physical-root value from a bad edit; bd launched from a deleted directory; extremely long Windows paths.

Related errors


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