hashicorp/nomad · error
no default Consul services client
Error message
no default Consul services client
What it means
ServiceClientWrapper.RegisterAgent in command/agent/consul/service_client.go looks up the service client for structs.ConsulDefaultCluster in an internal map. If no client has been registered for the default Consul cluster, it fails immediately with this error. It is a wrapper-layer invariant error: the multi-cluster Consul client map was never populated for the default cluster before agent registration was attempted.
Source
Thrown at command/agent/consul/service_client.go:511
scw.lock.Lock()
defer scw.lock.Unlock()
for _, serviceClient := range scw.serviceClients {
// TODO(tgross): we never return error from ServiceClient.Shutdown, so
// there's no point in returning it here either
_ = serviceClient.Shutdown()
}
return nil
}
func (scw *ServiceClientWrapper) RegisterAgent(role string, services []*structs.Service) error {
scw.lock.RLock()
defer scw.lock.RUnlock()
serviceClient, ok := scw.serviceClients[structs.ConsulDefaultCluster]
if !ok {
return errors.New("no default Consul services client")
}
return serviceClient.RegisterAgent(role, services)
}
func (scw *ServiceClientWrapper) RegisterWorkload(workload *serviceregistration.WorkloadServices) error {
scw.lock.RLock()
defer scw.lock.RUnlock()
clusters := scw.clustersInWorkload(workload)
if len(clusters) == 1 {
return scw.serviceClients[clusters[0]].RegisterWorkload(workload)
}
workloadsByCluster := scw.sliceWorkloadsByCluster(workload, clusters)
for cluster, workload := range workloadsByCluster {
err := scw.serviceClients[cluster].RegisterWorkload(workload)
if err != nil {
return errView on GitHub (pinned to 482b49bf1a)
Solutions
- Ensure the Consul client for structs.ConsulDefaultCluster is initialized and added to the ServiceClientWrapper before RegisterAgent is called (check startup order in setupServer/setupClient).
- Check the Nomad agent logs for earlier Consul client initialization failures (bad consul.address/TLS settings) that prevented the default client from being created.
- Verify the agent's `consul` configuration block is valid and Consul connectivity exists at startup.
- If embedding Nomad's service_client package, call the constructor that registers the default cluster client rather than building the map manually.
Example fix
// before: wrapper created with no default client
scw := &ServiceClientWrapper{serviceClients: map[string]ServiceClient{}}
scw.RegisterAgent(role, services) // panics into error
// after: register the default cluster client first
scw.serviceClients[structs.ConsulDefaultCluster] = serviceClient Defensive patterns
Strategy: try-catch
Validate before calling
// before agent self-registration, check the wrapper has the default client
if _, ok := wrapper.HasClient(structs.ConsulDefaultCluster); !ok {
return errors.New("consul default client not initialized; check consul config")
} Try / catch
if err := scw.RegisterAgent(role, services); err != nil {
if strings.Contains(err.Error(), "no default Consul services client") {
log.Error("Consul client not initialized at startup; verify consul block and init order")
return err
}
return err
} Prevention
- Initialize the Consul service client before calling setupServer/setupClient self-registration.
- Watch startup logs for Consul client init failures and fail fast.
- Validate the agent `consul` config block (address, TLS) before starting registration.
- In tests, use the constructor that registers the default cluster client.
When it happens
Trigger: Calling RegisterAgent(role, services) (via setupServer/setupClient) when scw.serviceClients lacks the structs.ConsulDefaultCluster entry — i.e. the Consul service client was not initialized/added before the Nomad agent registered its own services.
Common situations: Nomad agent config with Consul integration partially disabled or the consul client failing to initialize at startup; race at boot where agent self-registration runs before the default cluster client is added; custom code constructing a ServiceClientWrapper without calling the init/add for the default cluster.
Related errors
- error parsing port label %q from service %q: %v
- error parsing port %q from service %q: %v
- service %q contains invalid check: agent checks do not suppo
- panic(err)
- no one-time token returned
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/05653a0f4d83d684.
Report an issue: GitHub.