gastownhall/beads · error

ErrNotFound

ErrNotFound

Error message

%w: dolt not found on PATH: %v

What it means

Resolve wraps ErrNotFound when no explicit override (env or sidecar) is set and exec.LookPath("dolt") cannot find a dolt executable anywhere on the process's PATH. This is the final precedence level: PATH resolution failed and there is nothing to fall back to, so managed proxied-server mode cannot start.

Source

Thrown at internal/doltversion/resolve.go:142

		}
		return abs, SourceEnv, nil
	}

	if opts.SidecarValue != "" {
		abs, err := filepath.Abs(opts.SidecarValue)
		if err != nil {
			return "", SourceSidecar, fmt.Errorf("sidecar dolt binary %q: resolving absolute path: %w", opts.SidecarValue, err)
		}
		abs = completeExecutableExt(abs)
		if err := validateExplicitPath(abs); err != nil {
			return "", SourceSidecar, fmt.Errorf("sidecar dolt binary %q: %w", opts.SidecarValue, err)
		}
		return abs, SourceSidecar, nil
	}

	path, err := exec.LookPath("dolt")
	if err != nil {
		return "", SourcePath, fmt.Errorf("%w: dolt not found on PATH: %v", ErrNotFound, err)
	}
	return path, SourcePath, nil
}

// completeExecutableExt completes a Windows executable extension on an
// explicitly-named path spelled without one: BEADS_DOLT_BIN=C:\tools\dolt
// should find C:\tools\dolt.exe the same way cmd.exe or exec.LookPath
// would. os.Lstat has no PATHEXT concept, so without this the explicit
// path reported "not found" while dolt.exe sat right there. The exact
// spelled path wins when it exists (an operator who names an extensionless
// file gets that file); only when it does not is exec.LookPath consulted —
// on Windows, LookPath applies PATHEXT completion to paths that contain a
// separator without searching PATH. Non-Windows returns path unchanged:
// there, Unix has no implied-extension convention and LookPath's extra
// checks would only duplicate validateExplicitPath with a different error
// taxonomy.
func completeExecutableExt(path string) string {
	if runtime.GOOS != "windows" {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Install dolt (e.g. brew install dolt or download from dolt releases)
  2. Add dolt's directory to PATH for the process environment (check PATH inside the actual service context, not your shell)
  3. Set BEADS_DOLT_BIN to the absolute path of a known dolt binary as an explicit override
  4. In containers, copy the dolt binary into the image and reference it via BEADS_DOLT_BIN

Example fix

// before
# systemd unit: Environment=PATH=/usr/bin:/bin   (dolt is in /usr/local/bin)
// after
Environment=PATH=/usr/local/bin:/usr/bin:/bin
# or
Environment=BEADS_DOLT_BIN=/usr/local/bin/dolt
Defensive patterns

Strategy: fallback

Validate before calling

if _, err := exec.LookPath("dolt"); err != nil {
    return fmt.Errorf("dolt not found on PATH; install it or set BEADS_DOLT_BIN")
}

Try / catch

path, src, err := doltversion.Resolve(opts)
if errors.Is(err, doltversion.ErrNotFound) {
    return fmt.Errorf("dolt is not installed or not on PATH: %w", err)
}

Prevention

When it happens

Trigger: Calling Resolve with empty EnvValue and SidecarValue while no executable named "dolt" exists in any directory listed in the PATH environment variable.

Common situations: Dolt simply not installed; dolt installed but not on PATH in service/CI/container contexts (systemd units, cron, Docker images) that have a minimal PATH; installed via package manager under a name the service user can't see.

Related errors


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