vitessio/vitess · error

unknown vtctld client protocol: %s

Error message

unknown vtctld client protocol: %s

What it means

The vtctldclient package creates clients through a registry keyed by an explicit protocol string; New() returns this error when the passed protocol has no registered factory. Unlike the legacy client, the protocol is a parameter chosen by the caller (usually a flag in the consuming binary). It is a configuration/linkage error, not a network error.

Source

Thrown at go/vt/vtctl/vtctldclient/client.go:63

	if _, ok := registry[name]; ok {
		log.Fatalf("Register: %s already registered", name)
	}

	registry[name] = factory
}

// New returns a VtctldClient for the given protocol, connected to a
// VtctldServer on the given addr. This function returns an error if no client
// factory was registered for the given protocol.
//
// This is a departure from vtctlclient's New, which relies on a flag in the
// global namespace to determine the protocol to use. Instead, we require
// users to specify their own flag in their own (hopefully not global) namespace
// to determine the protocol to pass into here.
func New(ctx context.Context, protocol string, addr string) (VtctldClient, error) {
	factory, ok := registry[protocol]
	if !ok {
		return nil, fmt.Errorf("unknown vtctld client protocol: %s", protocol)
	}

	return factory(ctx, addr)
}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Blank-import the implementation: _ "vitess.io/vitess/go/vt/vtctl/vtctldclient/grpcvtctldclient"
  2. Correct the protocol flag value (typically "grpc") passed to vtctldclient.New
  3. Check for typos and case sensitivity in the protocol string
  4. Regenerate/rebuild any vtctldclient codegen'd client so the registry initialization is present

Example fix

// before
client, err := vtctldclient.New(ctx, "gprc", addr)
// after
import _ "vitess.io/vitess/go/vt/vtctl/vtctldclient/grpcvtctldclient"
client, err := vtctldclient.New(ctx, "grpc", addr)
Defensive patterns

Strategy: validation

Validate before calling

import _ "vitess.io/vitess/go/vt/vtctl/vtctldclient/grpcvtctldclient"
if protocol != "grpc" {
  return fmt.Errorf("unsupported protocol %q", protocol)
}

Type guard

func validVtctldProtocol(p string) bool { return p == "grpc" }

Try / catch

client, err := vtctldclient.New(ctx, protocol, addr)
if err != nil {
  if strings.Contains(err.Error(), "unknown vtctld client protocol") {
    return fmt.Errorf("check --vtctld_grpc_protocol and grpcvtctldclient import: %w", err)
  }
  return err
}

Prevention

When it happens

Trigger: Calling vtctldclient.New(ctx, protocol, addr) where protocol is not a key in registry — e.g. passing "grpc" without importing the grpc client package so its init never registers, or a typo like "gprc".

Common situations: Flag default not set or misspelled in a tool embedding vtctldclient; trimmed custom binary missing the grpcvtctldclient import; switching protocol names across Vitess versions.

Related errors


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