golang-migrate/migrate · error

bad scheme: %w

Error message

bad scheme: %w

What it means

"bad scheme: %w" is raised in rqlite's parseUrl (rqlite.go:289) when the URL scheme is not exactly "rqlite", wrapping ErrBadConfig. Open expects a rqlite:// (or rqlites-style) URL and rewrites it internally to http/https, so any other scheme is a configuration error. The wrapped error text will read e.g. 'bad scheme: bad parameter'.

Source

Thrown at database/rqlite/rqlite.go:289

		return &database.Error{OrigErr: err, Query: []byte(strings.Join(statements, "\n"))}
	}

	return nil
}

func parseUrl(url string) (*nurl.URL, *Config, error) {
	parsedUrl, err := nurl.Parse(url)
	if err != nil {
		return nil, nil, err
	}

	config, err := parseConfigFromQuery(parsedUrl.Query())
	if err != nil {
		return nil, nil, err
	}

	if parsedUrl.Scheme != "rqlite" {
		return nil, nil, fmt.Errorf("bad scheme: %w", ErrBadConfig)
	}

	// adapt from rqlite to http/https schemes
	if config.ConnectInsecure {
		parsedUrl.Scheme = "http"
	} else {
		parsedUrl.Scheme = "https"
	}

	filteredUrl := migrate.FilterCustomQuery(parsedUrl)

	return filteredUrl, config, nil
}

func parseConfigFromQuery(queryVals nurl.Values) (*Config, error) {
	c := Config{
		ConnectInsecure: DefaultConnectInsecure,
		MigrationsTable: DefaultMigrationsTable,

View on GitHub (pinned to 01a9643f14)

Solutions

  1. Change the URL scheme to rqlite:// (the driver maps it to http or https based on x-connect-insecure)
  2. If you have an https endpoint, keep rqlite scheme and rely on default TLS, or set x-connect-insecure=false
  3. Sanitize/validate the DSN scheme in code before calling migrate.New/WithURL

Example fix

// before
url := "http://localhost:4001"
d, err := rqlite.Open(url) // bad scheme
// after
url := "rqlite://localhost:4001?x-connect-insecure=true"
d, err := rqlite.Open(url)
Defensive patterns

Strategy: validation

Validate before calling

u, _ := url.Parse(dsn)
if u.Scheme != "rqlite" {
    return fmt.Errorf("expected rqlite:// scheme, got %q", u.Scheme)
}

Prevention

When it happens

Trigger: Calling rqlite.Open("http://localhost:4001/db") or "https://..." instead of "rqlite://..."; pasting an HTTP API endpoint URL directly into golang-migrate.

Common situations: Reusing the browser/API endpoint URL of an rqlite node as a DSN; environment variable DSNs set up for a different driver; scheme typos like rqlite+http.

Related errors


AI-assisted analysis of golang-migrate/migrate@01a9643f14 (2026-09-02). Data as JSON: /api/errors/bfe7f4f244ccafe0. Report an issue: GitHub.