gastownhall/beads · error
remote URL must not start with a dash
Error message
remote URL must not start with a dash
What it means
ValidateRemoteURL() rejects URLs beginning with '-' because exec.Command passes arguments directly to the dolt CLI — a URL like '-oProxyCommand=...' could be parsed as a flag (CLI flag injection). This is a deliberate security-boundary check applied to all remote URLs before they reach command arguments.
Source
Thrown at internal/remotecache/url.go:93
// that could be interpreted as CLI flags.
//
// This is a security boundary — all remote URLs should pass through this
// before reaching exec.Command arguments or SQL parameters.
func ValidateRemoteURL(rawURL string) error {
if rawURL == "" {
return fmt.Errorf("remote URL cannot be empty")
}
// Reject control characters (null bytes, newlines, tabs, etc.)
for i, c := range rawURL {
if c < 0x20 || c == 0x7f {
return fmt.Errorf("remote URL contains control character at position %d (0x%02x)", i, c)
}
}
// Reject leading dash (CLI flag injection via exec.Command arguments)
if strings.HasPrefix(rawURL, "-") {
return fmt.Errorf("remote URL must not start with a dash")
}
// SCP-style URLs (user@host:path) are validated separately
if gitSSHPattern.MatchString(rawURL) {
return validateSCPURL(rawURL)
}
// Parse as standard URL
return validateSchemeURL(rawURL)
}
// validateSchemeURL validates a scheme-based URL (https://, dolthub://, etc.)
func validateSchemeURL(rawURL string) error {
// net/url doesn't understand git+ssh:// etc., so we normalize first
normalizedURL := rawURL
scheme := ""
if idx := strings.Index(rawURL, "://"); idx > 0 {
scheme = rawURL[:idx]View on GitHub (pinned to 71377f2769)
Solutions
- Correct the call/config so the remote URL (starting with a scheme like dolthub:// or https://) is passed as the URL, and flags use their own flags.
- Inspect config/env sources for a leading '-' typo and remove it.
- If you need to pass something dash-prefixed, it is not a URL — use the proper parameter/flag instead.
- Add a caller-side check that the remote URL contains '://' or matches SCP-style user@host:path before invoking.
Example fix
// before: flag accidentally passed as URL
_, err := cache.Ensure(ctx, "-verbose")
// after: guard and pass a real URL
if !strings.Contains(remoteURL, "://") && !strings.Contains(remoteURL, "@") {
return fmt.Errorf("%q is not a remote URL", remoteURL)
}
_, err = cache.Ensure(ctx, remoteURL) Defensive patterns
Strategy: validation
Validate before calling
func looksLikeRemoteURL(s string) bool {
if strings.HasPrefix(s, "-") {
return false
}
return remotecache.IsRemoteURL(s)
}
// before calling Ensure:
if !looksLikeRemoteURL(arg) {
return fmt.Errorf("%q is not a remote URL (did you swap flag and URL?)", arg)
} Try / catch
if err := cache.Ensure(ctx, remoteURL); err != nil {
if strings.Contains(err.Error(), "must not start with a dash") {
return fmt.Errorf("argument parsing bug: %q used as URL; check flag order", remoteURL)
}
return err
} Prevention
- Always pass remote URLs as dedicated named flags/options, never positionally next to flags.
- Validate user input with ValidateRemoteURL as early as possible (CLI arg parsing stage).
- Treat any dash-leading value in a URL slot as an argument-order bug, not data.
- Escape or reject '-'-prefixed values in scripts that build bd commands dynamically.
When it happens
Trigger: ValidateRemoteURL (via Ensure or ValidateRemoteURLWithPatterns) receives a string whose first character is '-', e.g. a mangled config value, an argument-order bug where a flag was passed where the URL belongs, or a deliberately crafted input.
Common situations: Swapped CLI arguments (bd sync --remote -f); config file where the value got merged with a flag; hand-edited config with a stray dash; scripts passing options positionally into the URL slot.
Related errors
- remote URL cannot be empty
- remote URL contains control character at position %d (0x%02x
- no store is open for this workspace
- not found
- no absolute native user directory is available
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/7e23ddd9c95736f9.
Report an issue: GitHub.