googleapis/mcp-toolbox · error

sql.Open: %w

Error message

sql.Open: %w

What it means

initTiDBConnectionPool wraps sql.Open failures when constructing the TiDB connection pool. sql.Open only validates the driver name and DSN format — it does not connect — so this almost always indicates a malformed DSN or the mysql driver not being registered. The raw error is preserved with %w.

Source

Thrown at internal/sources/tidb/tidb.go:206

	match, err := regexp.MatchString(pattern, host)
	if err != nil {
		return false
	}
	return match
}

func initTiDBConnectionPool(ctx context.Context, tracer trace.Tracer, name, host, port, user, pass, dbname string, useSSL bool) (*sql.DB, error) {
	//nolint:all // Reassigned ctx
	ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name)
	defer span.End()

	// Configure the driver to connect to the database
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=true&charset=utf8mb4&tls=%t", user, pass, host, port, dbname, useSSL)

	// Interact with the driver directly as you normally would
	pool, err := sql.Open("mysql", dsn)
	if err != nil {
		return nil, fmt.Errorf("sql.Open: %w", err)
	}
	return pool, nil
}

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. URL-escape credentials with url.UserPassword or url.QueryEscape before building the DSN
  2. Verify TiDB source config fields: host, port (typically 4000), user, password, database are all set and valid
  3. Check the wrapped error for which DSN component the driver rejected
  4. If the driver is unregistered, ensure the mysql driver package is imported

Example fix

// before
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=true", user, pass, host, port, dbname)
// after
dsn := fmt.Sprintf("%s@tcp(%s:%s)/%s?parseTime=true", url.UserPassword(user, pass), host, port, dbname)
Defensive patterns

Strategy: validation

Validate before calling

func validateTiDBConfig(host, port, user, pass, dbname string) error {
    if host == "" || port == "" || user == "" || dbname == "" { return errors.New("tidb: host, port, user and database are required") }
    if _, err := strconv.Atoi(port); err != nil { return fmt.Errorf("tidb: invalid port %q", port) }
    if strings.ContainsAny(pass, "@:/") && url.QueryEscape(pass) == pass == false { /* escape below */ }
    _ = url.UserPassword(user, pass) // rejects invalid characters
    return nil
}

Try / catch

pool, err := initTiDBConnectionPool(...)
if err != nil {
    return fmt.Errorf("sql.Open failed: %w", err) // inspect wrapped driver message for bad DSN component
}

Prevention

When it happens

Trigger: Config.Initialize -> initTiDBConnectionPool where the composed DSN (user:pass@tcp(host:port)/dbname with parseTime, charset and tls params) is rejected by the mysql driver, e.g. invalid characters in user/password or unparseable DSN fields.

Common situations: Password containing special characters (@, :, /) that are not url-escaped before DSN composition; missing or malformed host/port from YAML config; empty dbname producing an invalid DSN.

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/3c6c68cf25b16a49. Report an issue: GitHub.