vitessio/vitess · critical

error creating vtsql proxy

Error message

error creating vtsql proxy: %w

What it means

cluster.New fails when vtsql.New cannot create the vtgate SQL proxy (DB) for the cluster. This happens after config parsing succeeds and usually means the connection/pool could not be established or initialized (e.g. vtgate unreachable at init, TLS failure). The wrapped error carries the vtsql.New cause.

Solutions

  1. Confirm vtgate is running and reachable at the configured host:port (nc/curl the port)
  2. Check TLS/credentials configuration for the vtsql connection
  3. Fix addresses, then restart vtadmin

Example fix

// before
vt: "-vtgate-host localhost -vtgate-port 15999"
// after
vt: "-vtgate-host vtgate.internal -vtgate-port 15999"
Defensive patterns

Strategy: validation

Validate before calling

// before starting vtadmin, verify vtgate reachability
host, port := vtgateAddrFromFlags(cfg.VtSQLFlags)
conn, err := net.DialTimeout("tcp", net.JoinHostPort(host, port), 3*time.Second)
if err != nil {
    return fmt.Errorf("vtgate %s:%s unreachable: %w", host, port, err)
}
conn.Close()

Try / catch

c, err := cluster.BuildCluster(ctx, cfg)
if err != nil {
    if strings.Contains(err.Error(), "error creating vtsql proxy") {
        return fmt.Errorf("cannot reach vtgate for cluster %q: %w", cfg.ID, err)
    }
    return err
}

Prevention

When it happens

Trigger: vtsql.New(ctx, vtsqlCfg) returns an error while building cluster.DB during vtadmin startup — e.g. vtgate address unresolvable/unreachable, TLS handshake failure with configured certs.

Common situations: vtgate down or wrong port; DNS failure; mTLS certs missing/expired; firewall blocking vtadmin->vtgate.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/f4b382df42a6f83a. Report an issue: GitHub.

Appendix: source

Thrown at go/vt/vtadmin/cluster/cluster.go:142

	for _, opt := range cfg.vtsqlConfigOpts {
		vtsqlCfg = opt(vtsqlCfg)
	}

	vtctldargs := buildPFlagSlice(cfg.VtctldFlags)

	vtctldCfg, err := vtctldclient.Parse(protocluster, disco, vtctldargs)
	if err != nil {
		return nil, fmt.Errorf("error creating vtctldclient proxy config: %w", err)
	}

	for _, opt := range cfg.vtctldConfigOpts {
		vtctldCfg = opt(vtctldCfg)
	}

	cluster.DB, err = vtsql.New(ctx, vtsqlCfg)
	if err != nil {
		return nil, fmt.Errorf("error creating vtsql proxy: %w", err)
	}

	cluster.Vtctld, err = vtctldclient.New(ctx, vtctldCfg)
	if err != nil {
		return nil, fmt.Errorf("error creating vtctldclient: %w", err)
	}

	if cfg.TabletFQDNTmplStr != "" {
		cluster.TabletFQDNTmpl, err = template.New(cluster.ID + "-tablet-fqdn").Parse(cfg.TabletFQDNTmplStr)
		if err != nil {
			return nil, fmt.Errorf("failed to parse tablet fqdn template %s: %w", cfg.TabletFQDNTmplStr, err)
		}
	}

	cluster.backupReadPool = cfg.BackupReadPoolConfig.NewReadPool()
	cluster.schemaReadPool = cfg.SchemaReadPoolConfig.NewReadPool()
	cluster.topoRWPool = cfg.TopoRWPoolConfig.NewRWPool()
	cluster.topoReadPool = cfg.TopoReadPoolConfig.NewReadPool()

View on GitHub (pinned to 01a25a7d17)