gastownhall/beads · error

remote URL has no scheme (expected one of: %s)

Error message

remote URL has no scheme (expected one of: %s)

What it means

ValidateRemoteURL (via validateSchemeURL) splits the input on "://" to extract a scheme; if none is found, the string is not treated as a remote URL. This library only accepts dolt remote URLs with an explicit scheme (dolthub, https, s3, gs, az, oci, file, ssh, git, git+*, aws). A bare hostname or local path fails here.

Source

Thrown at internal/remotecache/url.go:120

	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]
		// 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

View on GitHub (pinned to 71377f2769)

Solutions

  1. Add the appropriate scheme prefix, e.g. "dolthub://myorg/myrepo" instead of "myorg/myrepo"
  2. For a local path, use "file:///path/to/dir" instead of a bare path
  3. If SCP-style was intended, use the user@host:path form (e.g. git@github.com:org/repo)

Example fix

// before
remote := "myorg/myrepo"
_ = remotecache.ValidateRemoteURL(remote)
// after
remote := "dolthub://myorg/myrepo"
_ = remotecache.ValidateRemoteURL(remote)
Defensive patterns

Strategy: validation

Validate before calling

func hasScheme(u string) bool {
	i := strings.Index(u, "://")
	return i > 0
}
if !hasScheme(remote) && !strings.Contains(remote, "@") {
	remote = "dolthub://" + remote // or prompt the user for a full URL
}

Type guard

func isRemoteURL(s string) bool {
	return strings.Contains(s, "://") || regexp.MustCompile(`^[^@]+@[^@]+:.+$`).MatchString(s)
}

Try / catch

if err := remotecache.ValidateRemoteURL(u); err != nil {
	if strings.Contains(err.Error(), "has no scheme") {
		u = "dolthub://" + u // apply default scheme and retry
	}
}

Prevention

When it happens

Trigger: Calling remotecache.ValidateRemoteURL (or ValidateRemoteURLWithPatterns) with a string that contains no "://" separator and does not match the SCP pattern user@host:path, e.g. "myorg/myrepo" or "example.com/repo".

Common situations: Users paste a Dolthub org/repo shorthand without the dolthub:// prefix, pass a local directory path, or omit the scheme in a config file/env var where the full URL was expected.

Related errors


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