vitessio/vitess · error
ErrImplementationNotRegistered
ErrImplementationNotRegistered
Error message
%w %s
What it means
Discovery.New looks up the requested discovery implementation (e.g. "consul", "etcd", "vitesstopology") in a package-level registry populated by init() functions. If the impl string is not registered, the constructor fails with ErrImplementationNotRegistered wrapped together with the impl name. This guards against building a cluster whose discovery backend does not exist or was never linked in.
Source
Thrown at go/vt/vtadmin/cluster/discovery/discovery.go:121
_, ok := registry[name]
if ok {
panic("[discovery] factory already registered for " + name)
}
registry[name] = factory
}
// New returns a Discovery implementation using the registered factory for the
// implementation. Usage of the args slice is dependent on the implementation's
// factory.
func New(impl string, cluster *vtadminpb.Cluster, args []string) (Discovery, error) {
registryMu.Lock()
factory, ok := registry[impl]
registryMu.Unlock()
if !ok {
return nil, fmt.Errorf("%w %s", ErrImplementationNotRegistered, impl)
}
return factory(cluster, pflag.NewFlagSet("discovery:"+impl, pflag.ContinueOnError), args)
}
func init() {
Register("consul", NewConsul)
Register("staticfile", NewStaticFile)
Register("dynamic", NewDynamic)
}
View on GitHub (pinned to 01a25a7d17)
Solutions
- Correct the impl string to a registered implementation name (check registry keys / available impl packages).
- Add a blank import of the implementation package in your binary so its init() registers the factory (e.g. _ "vitess.io/vitess/go/vt/vtadmin/cluster/discovery/implconsul").
- Compare your flag/env value against the impl names registered in the discovery package before calling New.
Example fix
// before
import "vitess.io/vitess/go/vt/vtadmin/cluster/discovery"
d, err := discovery.New("consul", cluster, args) // impl package never imported
// after
import (
_ "vitess.io/vitess/go/vt/vtadmin/cluster/discovery/implconsul"
"vitess.io/vitess/go/vt/vtadmin/cluster/discovery"
)
d, err := discovery.New("consul", cluster, args) Defensive patterns
Strategy: validation
Validate before calling
// ensure the impl package is linked and the name is registered before New
switch impl {
case "consul", "etcd2":
// known registered implementations
default:
return fmt.Errorf("unsupported discovery impl %q", impl)
} Try / catch
d, err := discovery.New(impl, cluster, args)
if err != nil {
if errors.Is(err, discovery.ErrImplementationNotRegistered) {
log.Fatalf("discovery impl %q not registered; check imports/config", impl)
}
return err
} Prevention
- Add blank imports (_ ".../discovery/implconsul") for every implementation your binary supports.
- Keep the impl string in one shared constant used by both registration and lookup.
- Compare configured impl values against the registry keys in a startup smoke test.
When it happens
Trigger: Calling discovery.New("myimpl", cluster, args) with an impl name that no registered factory provides; can also occur when the package containing the implementation's init() is not imported into the binary, so its factory never registers.
Common situations: Typo in the discovery impl flag (e.g. "consul" misspelled), building a custom binary that forgot to import the implementation package (blank import _ "...discovery/implconsul"), or renaming an implementation without updating deployment configs.
Related errors
- failed to generate vtgate consul datacenter from template: %
- parse error
- ReadFile cannot be called on read-write backup
- AddFile cannot be called on read-only backup
- EndBackup cannot be called on read-only backup
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/45261926df0af94e.
Report an issue: GitHub.