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
- Blank-import the gRPC client implementation so its init registers the factory: _ "vitess.io/vitess/go/vt/vtctl/vtctlclient/grpcvtctlclient"
- Check the vtctl_client_protocol flag value matches a registered protocol (e.g. grpc)
- Build the standard vtctlclient/vtctl binaries instead of a trimmed custom binary
- 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
- Always blank-import grpcvtctlclient in binaries using vtctlclient
- Pin the -vtctl_client_protocol flag to a known value in scripts
- Smoke-test custom builds with a trivial vtctl command before deploying
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
- unknown vtctld client protocol: %s
- --batch-size requires 'direct' ddl_strategy
- --batch-size conflicts with --uuid-list. Batching does not s
- --batch-size only allowed when all queries are CREATE TABLE|
- failed to load static auth plugin. Plugin configured but grp
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/6c6e7f8b4f06704e.
Report an issue: GitHub.