vitessio/vitess · error

unknown vtctl client protocol: %v

Error message

unknown vtctl client protocol: %v

What it means

The legacy vtctl client library resolves its implementation through a factory registry keyed by the vtctlClientProtocol package variable. When New() looks up the protocol and finds no registered factory, it refuses to build a client with this error. It means the binary was linked without any client implementation registered for the configured protocol.

Source

Thrown at go/vt/vtctl/vtctlclient/interface.go:78

// Factory functions are registered by client implementations
type Factory func(ctx context.Context, addr string) (VtctlClient, error)

var factories = make(map[string]Factory)

// RegisterFactory allows a client implementation to register itself.
func RegisterFactory(name string, factory Factory) {
	if _, ok := factories[name]; ok {
		log.Error(fmt.Sprintf("RegisterFactory: %s already exists", name))
		os.Exit(1)
	}
	factories[name] = factory
}

// New allows a user of the client library to get its implementation.
func New(ctx context.Context, addr string) (VtctlClient, error) {
	factory, ok := factories[vtctlClientProtocol]
	if !ok {
		return nil, fmt.Errorf("unknown vtctl client protocol: %v", vtctlClientProtocol)
	}
	return factory(ctx, addr)
}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Blank-import the gRPC client implementation so its init registers the factory: _ "vitess.io/vitess/go/vt/vtctl/vtctlclient/grpcvtctlclient"
  2. Check the vtctl_client_protocol flag value matches a registered protocol (e.g. grpc)
  3. Build the standard vtctlclient/vtctl binaries instead of a trimmed custom binary
  4. Verify with go build that the binary includes the implementation package

Example fix

// before
import "vitess.io/vitess/go/vt/vtctl/vtctlclient"
// after
import (
  _ "vitess.io/vitess/go/vt/vtctl/vtctlclient/grpcvtctlclient"
  "vitess.io/vitess/go/vt/vtctl/vtctlclient"
)
Defensive patterns

Strategy: validation

Validate before calling

// before dialing, ensure the grpc implementation is linked
import _ "vitess.io/vitess/go/vt/vtctl/vtctlclient/grpcvtctlclient"

Type guard

func clientFactoryRegistered(protocol string) bool {
  return protocol == "grpc" // only registered protocol in stock builds
}

Try / catch

client, err := vtctlclient.New(ctx, addr)
if err != nil {
  if strings.Contains(err.Error(), "unknown vtctl client protocol") {
    return fmt.Errorf("client not linked for protocol; import grpcvtctlclient: %w", err)
  }
  return err
}

Prevention

When it happens

Trigger: Calling vtctlclient.New(ctx, addr) (directly or via RunCommandAndWait) when vtctlClientProtocol is set to a value for which no factory was registered via the RegisterXxxClient init hooks (e.g. gRPC client package not imported/linked).

Common situations: Building a custom vtctl binary that forgot to import the grpc vtctlclient implementation; running 'go run' on a subset of packages; flag misconfiguration setting an unsupported protocol value.

Related errors


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