gastownhall/beads · error

dolt remote -v failed: %s: %w

Error message

dolt remote -v failed: %s: %w

What it means

ListCLIRemotes shells out to 'dolt remote -v' in the database directory to enumerate CLI-level remotes. If the subprocess exits non-zero, this error wraps the combined output and the exec error. It means the dolt CLI could not list remotes (or dolt isn't a usable binary there).

Source

Thrown at internal/storage/doltutil/remotes.go:124

	remotes := make([]storage.RemoteInfo, 0, len(state.Remotes))
	for name, r := range state.Remotes {
		remotes = append(remotes, storage.RemoteInfo{Name: name, URL: r.URL})
	}
	sort.Slice(remotes, func(i, j int) bool { return remotes[i].Name < remotes[j].Name })
	return remotes, nil
}

// ListCLIRemotes parses `dolt remote -v` output from the given database
// directory. This is a read-only guard for deciding whether CLI push/pull/fetch
// can safely run from that directory; remote mutation still goes through SQL.
func ListCLIRemotes(dbPath string) ([]storage.RemoteInfo, error) {
	ctx, cancel := context.WithTimeout(context.Background(), listCLIRemotesTimeout(dbPath))
	defer cancel()
	cmd := exec.CommandContext(ctx, "dolt", "remote", "-v") // #nosec G204 -- fixed command
	cmd.Dir = dbPath
	out, err := cmd.CombinedOutput()
	if err != nil {
		return nil, fmt.Errorf("dolt remote -v failed: %s: %w", strings.TrimSpace(string(out)), err)
	}

	seen := map[string]bool{}
	var remotes []storage.RemoteInfo
	for _, line := range strings.Split(strings.TrimSpace(string(out)), "\n") {
		line = strings.TrimSpace(line)
		if line == "" {
			continue
		}
		parts := strings.Fields(line)
		if len(parts) >= 2 && !seen[parts[0]] {
			seen[parts[0]] = true
			remotes = append(remotes, storage.RemoteInfo{Name: parts[0], URL: parts[1]})
		}
	}
	return remotes, nil
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Run 'dolt remote -v' manually in dbPath to see the same failure.
  2. Install/upgrade the dolt binary and confirm it is on PATH.
  3. Verify dbPath is a valid Dolt database directory (contains .dolt).
  4. If timeouts occur, check system load or dolt startup latency.

Example fix

// before
cmd := exec.Command("dolt", "remote", "-v") // dolt not on PATH
// after
if _, err := exec.LookPath("dolt"); err != nil {
    return nil, fmt.Errorf("dolt binary not found: %w", err)
}
cmd := exec.Command("dolt", "remote", "-v")
Defensive patterns

Strategy: fallback

Validate before calling

if _, err := exec.LookPath("dolt"); err != nil { return errors.New("dolt CLI not installed") }

Try / catch

remotes, err := doltutil.ListCLIRemotes(dbPath)
if err != nil {
    // fall back to persisted remotes from repo_state.json
    remotes, err = doltutil.PersistedRemotes(dbPath)
    if err != nil { return err }
}

Prevention

When it happens

Trigger: Calling ListCLIRemotes/FindCLIRemote when the dolt binary is missing, not executable, the directory is not a valid Dolt database, or the command exceeds the timeout.

Common situations: dolt not installed or not on PATH; running in a directory without .dolt; outdated dolt binary; slow spawn hitting the context timeout.

Related errors


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