gastownhall/beads · error

invalid remote URL: %w

Error message

invalid remote URL: %w

What it means

BootstrapFromRemoteWithDB clones a Dolt database from a configured sync.remote URL when no local .beads/dolt/ exists. Before cloning, it validates the URL with remotecache.ValidateRemoteURL and wraps any failure as "invalid remote URL". This means the configured remote is malformed or uses an unsupported scheme, so bootstrap refuses to shell out to `dolt clone`.

Source

Thrown at internal/storage/dolt/bootstrap.go:55

// BootstrapFromGitRemote is deprecated. Use BootstrapFromRemote instead.
func BootstrapFromGitRemote(ctx context.Context, doltDir, gitRemoteURL string) (bool, error) {
	return BootstrapFromRemote(ctx, doltDir, gitRemoteURL)
}

// BootstrapFromRemoteWithDB is like BootstrapFromRemote but allows
// specifying the database name (used by the embedded driver for the
// subdirectory structure). The database parameter must not be empty;
// callers should use cfg.GetDoltDatabase() which applies the fallback chain
// (env var → config → default).
func BootstrapFromRemoteWithDB(ctx context.Context, doltDir, remoteURL, database string) (bool, error) {
	// Skip if Dolt database already exists
	if doltExists(doltDir) {
		return false, nil
	}

	if err := remotecache.ValidateRemoteURL(remoteURL); err != nil {
		return false, fmt.Errorf("invalid remote URL: %w", err)
	}

	if err := ValidateDatabaseName(database); err != nil {
		return false, fmt.Errorf("invalid database name %q (use cfg.GetDoltDatabase() to resolve the configured name): %w", database, err)
	}

	// Verify dolt CLI is available
	if _, err := exec.LookPath("dolt"); err != nil {
		return false, fmt.Errorf("dolt CLI not found (required for remote bootstrap): %w", err)
	}

	// Create the parent dolt directory
	if err := os.MkdirAll(doltDir, 0o750); err != nil {
		return false, fmt.Errorf("failed to create dolt directory: %w", err)
	}

	// Clone into <doltDir>/<database>/ so the embedded driver can find it.
	// `dolt clone <url> <target>` creates <target>/.dolt/ directly.

View on GitHub (pinned to 71377f2769)

Solutions

  1. Print and inspect the URL: `bd config get sync.remote` or read .beads/config.yaml, then fix the value to a valid remote URL (git https/ssh, DoltHub, S3, GCS, or file URL accepted by ValidateRemoteURL).
  2. If the value came from an environment variable, verify it is actually set and has no surrounding quotes/whitespace: `echo "$BEADS_REMOTE"`.
  3. Run `bd doctor` or call remotecache.ValidateRemoteURL in a scratch program to see the precise validation failure and the accepted URL formats.
  4. If you intend no remote, remove the sync.remote key entirely so bootstrap does not attempt a clone.

Example fix

# before (.beads/config.yaml)
sync:
  remote: my-remote-url
# after
sync:
  remote: https://doltremoteapi.dolthub.com/org/beads
Defensive patterns

Strategy: validation

Validate before calling

if err := remotecache.ValidateRemoteURL(remoteURL); err != nil {
    return fmt.Errorf("fix sync.remote before bootstrapping: %w", err)
}

Try / catch

ok, err := dolt.BootstrapFromRemote(ctx, doltDir, remote)
if err != nil && strings.Contains(err.Error(), "invalid remote URL") {
    // surface config guidance: check sync.remote in .beads/config.yaml
    return fmt.Errorf("check `bd config get sync.remote`: %w", err)
}

Prevention

When it happens

Trigger: Calling BootstrapFromRemote/BootstrapFromRemoteWithDB (or `bd bootstrap`) when config.yaml sync.remote (or the remoteURL argument) is empty, malformed, or uses a scheme rejected by ValidateRemoteURL.

Common situations: Typos in the remote URL in .beads/config.yaml; a file:// or relative path pasted where a git/DoltHub/S3/GCS URL is expected; an env-var-substituted remote that resolved to an empty string; hand-edited config with stray whitespace or quotes.

Related errors


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