gastownhall/beads · error
remote URL cannot be empty
Error message
remote URL cannot be empty
What it means
ValidateRemoteURL() is the package's security boundary: every remote URL must pass it before being used in exec.Command arguments or SQL parameters. This error fires first when the URL string is empty — there is nothing to validate or clone from.
Source
Thrown at internal/remotecache/url.go:81
func IsRemoteURL(s string) bool {
for _, scheme := range remoteSchemes {
if strings.HasPrefix(s, scheme) {
return true
}
}
return gitSSHPattern.MatchString(s)
}
// ValidateRemoteURL performs strict security validation on a remote URL.
// It rejects URLs containing control characters (including null bytes),
// validates structural correctness per scheme, and rejects leading dashes
// 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)
}View on GitHub (pinned to 71377f2769)
Solutions
- Set the remote URL before calling: e.g. dolthub://org/repo in bd config or the relevant env var.
- Check where the value originates (config file key present and non-empty, env var set) and fail fast with a clearer upstream message.
- Guard callers: skip cache operations entirely when no remote is configured instead of passing an empty string.
- Run `bd doctor`/config inspection to confirm the remote is configured.
Example fix
// before: calling with possibly-empty config value
_, err := cache.Ensure(ctx, cfg.RemoteURL)
// after: fail early with a clear message
if cfg.RemoteURL == "" {
return fmt.Errorf("no remote configured: set remote_url in .beads/beads.json")
}
_, err := cache.Ensure(ctx, cfg.RemoteURL) Defensive patterns
Strategy: validation
Validate before calling
func validateBeforeUse(remoteURL string) error {
if strings.TrimSpace(remoteURL) == "" {
return fmt.Errorf("remote URL is not configured")
}
return remotecache.ValidateRemoteURL(remoteURL)
} Try / catch
if err := validateBeforeUse(cfg.RemoteURL); err != nil {
return fmt.Errorf("check .beads/beads.json remote_url: %w", err)
}
return cache.Ensure(ctx, cfg.RemoteURL) Prevention
- Validate config at load time; fail with a clear 'remote not configured' message instead of a empty URL reaching the cache.
- Avoid the zero-value trap: never pass an unset string variable as remoteURL.
- Check env vars with os.LookupEnv to distinguish unset from empty.
- Document the expected URL format (dolthub://org/repo) in config examples.
When it happens
Trigger: Cache.Ensure(ctx, "") or ValidateRemoteURL("") / ValidateRemoteURLWithPatterns("", ...) with an unset remote URL — typically a missing config value, empty env var, or a function receiving an uninitialized variable.
Common situations: bd config file missing the remote/peer URL field; environment variable (e.g. for the remote) empty in CI; a code path building the URL from parts where the variable part resolved to empty; deserialized config with a blank value.
Related errors
- remote URL contains control character at position %d (0x%02x
- remote URL must not start with a dash
- unknown backend %q (want one of: %s)
- directory path is empty
- prefix mismatch: database uses '%s' (allowed: %s) but you sp
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/ddef898911cc4d9c.
Report an issue: GitHub.