gastownhall/beads · error
remote URL is malformed: %w
Error message
remote URL is malformed: %w
What it means
The scheme passed the allowlist but net/url could not parse the (normalized) URL. The underlying url.Parse error is wrapped, so errors.Is/As against *url.Error works. For git+* schemes the library rewrites the scheme to "placeholder" before parsing to work around net/url limitations.
Source
Thrown at internal/remotecache/url.go:129
scheme = rawURL[:idx]
// For net/url parsing, replace git+ssh with a parseable scheme
if strings.HasPrefix(scheme, "git+") {
normalizedURL = rawURL[len(scheme)+3:] // strip scheme://
normalizedURL = "placeholder://" + normalizedURL
}
}
if scheme == "" {
return fmt.Errorf("remote URL has no scheme (expected one of: %s)", strings.Join(sortedSchemes(), ", "))
}
if !allowedSchemes[scheme] {
return fmt.Errorf("remote URL scheme %q is not allowed (expected one of: %s)", scheme, strings.Join(sortedSchemes(), ", "))
}
parsed, err := url.Parse(normalizedURL)
if err != nil {
return fmt.Errorf("remote URL is malformed: %w", err)
}
// Scheme-specific structural validation
switch scheme {
case "dolthub":
// dolthub://org/repo — requires org and repo
p := strings.TrimPrefix(parsed.Path, "/")
host := parsed.Host
combined := host
if p != "" {
combined = host + "/" + p
}
parts := strings.Split(combined, "/")
if len(parts) < 2 || parts[0] == "" || parts[1] == "" {
return fmt.Errorf("dolthub:// URL must have org/repo format (e.g., dolthub://myorg/myrepo)")
}
case "https", "http", "git+https", "git+http":
if parsed.Host == "" {View on GitHub (pinned to 71377f2769)
Solutions
- Fix the URL syntax per the wrapped *url.Error message (bad host, invalid port, invalid escape)
- Percent-encode special characters in path/query portions (e.g. spaces as %20)
- Quote the URL in shell/config so interpolation doesn't corrupt it
Example fix
// before remote := "https://my host.example.com/repo" // after remote := "https://my-host.example.com/repo"
Defensive patterns
Strategy: validation
Validate before calling
func parseableURL(u string) error {
_, err := url.Parse(u)
return err
}
if err := parseableURL(remote); err != nil {
return fmt.Errorf("bad remote URL %q: %w", remote, err)
} Type guard
func isParseableURL(s string) bool {
_, err := url.Parse(s)
return err == nil
} Try / catch
if err := remotecache.ValidateRemoteURL(u); err != nil {
var urlErr *url.Error
if errors.As(err, &urlErr) {
return fmt.Errorf("malformed remote URL %q: %v", u, urlErr.Err)
}
} Prevention
- Run url.Parse on URLs at config-load time to fail fast
- Percent-encode user-supplied path segments
- Quote URLs in shell commands and config files
When it happens
Trigger: ValidateRemoteURL with a structurally invalid URL for an allowed scheme, e.g. "https://[bad::ipv6", "http://exa mple.com", or a URL with invalid percent-encoding like "https://h/%zz".
Common situations: Copy-paste errors introducing stray spaces or brackets, shell expansions mangling the URL, or hand-assembled URLs with unescaped/invalid characters.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/764f5fb6767e1b76.
Report an issue: GitHub.