temporalio/temporal · error
missingServiceInStaticHosts
missingServiceInStaticHosts
Error message
%w: %v
What it means
Sentinel error missingServiceInStaticHosts wrapped with the offending service name. When static hosts are provided via WithHosts (hostsByService), every default service (frontend, history, matching, worker, etc.) must have at least one host entry; a missing entry aborts server construction.
Source
Thrown at temporal/fx.go:292
esHttpClient, err = esclient.NewAwsHttpClient(esConfig.AWSRequestSigning)
if err != nil {
return serverOptionsProvider{}, fmt.Errorf("unable to create AWS HTTP client for Elasticsearch: %w", err)
}
}
esClient, err = esclient.NewClient(esConfig, esHttpClient, logger)
if err != nil {
return serverOptionsProvider{}, fmt.Errorf("unable to create Elasticsearch client (URL = %v, username = %q): %w",
esConfig.URL.Redacted(), esConfig.Username, err)
}
}
// check that when static hosts are defined, they are defined for all required hosts
if len(so.hostsByService) > 0 {
for _, service := range DefaultServices {
hosts := so.hostsByService[primitives.ServiceName(service)]
if len(hosts.All) == 0 {
return serverOptionsProvider{}, fmt.Errorf("%w: %v", missingServiceInStaticHosts, service)
}
}
}
if so.config.Global.Authorization.RemoteClusterAuth.Require && so.tokenProvider == nil {
return serverOptionsProvider{}, errors.New("global.authorization.remoteClusterAuth.require is true but no TokenProvider is configured: use WithTokenProvider")
}
// TokenCredentials require TLS (RFC 9700); without a remote-cluster TLS source the first
// cross-cluster dial would fatal-log, with no clear "you forgot TLS" diagnostic.
// Coarse check: any remote-cluster TLS entry passes; per-hostname config is still validated
// lazily on first dial.
if so.tokenProvider != nil && so.tlsConfigProvider == nil && len(so.config.Global.TLS.RemoteClusters) == 0 {
return serverOptionsProvider{}, errors.New("WithTokenProvider is set but no remote-cluster TLS is configured: supply global.tls.remoteClusters in config, or pass a provider via WithTLSConfigProvider")
}
return serverOptionsProvider{
ServerOptions: so,
StopChan: stopChan,View on GitHub (pinned to bde624efd1)
Solutions
- Add the missing service to the WithHosts map with at least one host
- Reconcile the host map against temporal.DefaultServices programmatically
- If static hosts are no longer needed, remove WithHosts and rely on default membership resolution
Example fix
// before
opts := temporal.WithHosts(map[primitives.ServiceName]temporal.Hosts{
primitives.FrontendService: {All: []string{"h1:7233"}},
primitives.HistoryService: {All: []string{"h1:7234"}},
})
// after
opts := temporal.WithHosts(map[primitives.ServiceName]temporal.Hosts{
primitives.FrontendService: {All: []string{"h1:7233"}},
primitives.HistoryService: {All: []string{"h1:7234"}},
primitives.MatchingService: {All: []string{"h1:7235"}},
primitives.WorkerService: {All: []string{"h1:7239"}},
}) Defensive patterns
Strategy: validation
Validate before calling
for _, svc := range temporal.DefaultServices {
if len(hostsByService[svc].All) == 0 {
return fmt.Errorf("missing static hosts for %s", svc)
}
} Prevention
- Iterate temporal.DefaultServices (not a hand-written list) when building host maps
- Add a unit test asserting every default service has hosts
- Regenerate host maps when new Temporal services are introduced
When it happens
Trigger: Calling WithHosts with a map that omits one of temporal.DefaultServices; any service name in the map has an empty hosts.All list.
Common situations: Adding a new Temporal service (e.g. internal-frontend) to DefaultServices but not updating the static host map in operator tooling or tests; copy-pasted host config that forgot one service.
Related errors
- Current cluster name is empty
- unknown archiver scheme
- unable to find archiver config for the given scheme
- no bucket specified
- empty aws region
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/750575d93165ead2.
Report an issue: GitHub.