gastownhall/beads · error
invalid remote URL: %w
Error message
invalid remote URL: %w
What it means
AddCLIRemote validates the remote URL with remotecache.ValidateRemoteURL before shelling out to `dolt remote add`. When the URL fails validation (empty value, unsupported scheme, embedded whitespace/control characters), the function aborts without invoking dolt and wraps the validator's error with "invalid remote URL". This guard exists so unvalidated strings never reach the dolt subprocess argv.
Source
Thrown at internal/storage/doltutil/remotes.go:162
func RemoteURLsMatch(got, want string) bool {
if got == "" || want == "" {
return got == want
}
if got == want || doltremote.Normalize(got) == doltremote.Normalize(want) {
return true
}
return false
}
// AddCLIRemote adds a remote at the filesystem level via dolt CLI.
// Remote mutation should normally go through SQL; this is reserved for the
// local CLI mirror required by subprocess push/pull/fetch routing.
func AddCLIRemote(dbPath, name, url string) error {
if err := remotecache.ValidateRemoteName(name); err != nil {
return fmt.Errorf("invalid remote name: %w", err)
}
if err := remotecache.ValidateRemoteURL(url); err != nil {
return fmt.Errorf("invalid remote URL: %w", err)
}
cmd := exec.Command("dolt", "remote", "add", name, url) // #nosec G204 -- validated argv
cmd.Dir = dbPath
out, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("dolt remote add failed: %s: %w", strings.TrimSpace(string(out)), err)
}
return nil
}
// RemoveCLIRemote removes a remote at the filesystem level via dolt CLI.
func RemoveCLIRemote(dbPath, name string) error {
if err := remotecache.ValidateRemoteName(name); err != nil {
return fmt.Errorf("invalid remote name: %w", err)
}
cmd := exec.Command("dolt", "remote", "remove", name) // #nosec G204 -- validated argv
cmd.Dir = dbPath
out, err := cmd.CombinedOutput()View on GitHub (pinned to 71377f2769)
Solutions
- Log or print the exact url value passed to EnsureCLIRemote/AddCLIRemote to see what is actually being validated
- Correct the remote URL in your beads/dolt config to a full, valid http(s) URL
- Trim surrounding whitespace and control characters from the configured value
- If the URL looks valid, review remotecache.ValidateRemoteURL — the wrapped error states the specific rule violated
Example fix
// before EnsureCLIRemote(dbPath, "origin", "git@github.com:me/beads.git") // scp-style URL rejected // after EnsureCLIRemote(dbPath, "origin", "https://github.com/me/beads.git")
Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(remoteURL)
if err != nil || u.Scheme == "" || u.Host == "" {
return fmt.Errorf("remote URL must be absolute with a host, got %q", remoteURL)
}
if strings.TrimSpace(remoteURL) != remoteURL {
return fmt.Errorf("remote URL has surrounding whitespace")
} Type guard
func isValidRemoteURL(u string) bool {
parsed, err := url.Parse(u)
return err == nil && (parsed.Scheme == "http" || parsed.Scheme == "https") && parsed.Host != "" && u == strings.TrimSpace(u)
} Prevention
- Store remote URLs as full http(s) URLs in config, never scp-style git shorthand
- Trim whitespace when loading URLs from env vars, flags, or config files
- Validate config once at startup so bad URLs fail before any sync command runs
When it happens
Trigger: Calling AddCLIRemote or EnsureCLIRemote with a url that fails ValidateRemoteURL: an empty string, a value without a supported scheme (e.g. "htp://..." or a bare "github.com/me/repo"), or a URL containing spaces or control characters.
Common situations: Typo'd remote URL in beads sync config; trailing whitespace from copy-pasting a URL; passing an scp-style git URL (git@host:path) where dolt expects http(s); an unset config key interpolated as an empty string.
Related errors
- invalid --dolt-auto-commit=%q (valid: off, on, batch)
- invalid remote name: %w
- got %d close reasons for %d issue IDs; provide exactly one s
- cannot specify both --reason-file and --reason/--resolution/
- --reason-file %q is empty; close reason is required
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/deae8cb5db0c6bb9.
Report an issue: GitHub.