temporalio/temporal · error
unable to create Elasticsearch client (URL = %v, username =
Error message
unable to create Elasticsearch client (URL = %v, username = %q): %w
What it means
Wraps a failure from esclient.NewClient while constructing the Elasticsearch client used by Temporal's visibility store during server bootstrap. The wrapper includes the redacted ES URL and username to help identify the misconfigured datastore. Temporal cannot start visibility persistence until a valid ES client is built, so this aborts startup.
Source
Thrown at temporal/fx.go:282
if persistenceConfig.VisibilityConfigExist() &&
persistenceConfig.DataStores[persistenceConfig.VisibilityStore].Elasticsearch != nil {
esConfig = persistenceConfig.DataStores[persistenceConfig.VisibilityStore].Elasticsearch
esConfig.SetHttpClient(so.elasticsearchHttpClient)
}
if esConfig != nil {
esHttpClient := so.elasticsearchHttpClient
if esHttpClient == nil {
var err error
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 firstView on GitHub (pinned to bde624efd1)
Solutions
- Fix the elasticsearch.url in the persistence datastore config (must be a valid, parseable URL)
- Verify elasticsearch username/password and AWSRequestSigning settings are consistent
- Check the wrapped root error (%w) for the underlying cause from the ES client library
- Test the ES endpoint is reachable with curl before starting Temporal
Example fix
// before (config)
datastores:
es-visibility:
elasticsearch:
url: "elasticsearchover:9200" # invalid URL
// after
datastores:
es-visibility:
elasticsearch:
url: "http://elasticsearch:9200"
username: "admin"
password: "secret" Defensive patterns
Strategy: validation
Validate before calling
cfg := persistenceConfig.DataStores[store].Elasticsearch
if cfg == nil { return nil }
if _, err := url.Parse(string(cfg.URL)); err != nil {
return fmt.Errorf("invalid elasticsearch url: %w", err)
}
if cfg.Username == "" && !cfg.AWSRequestSigning.IsSet() {
return errors.New("elasticsearch credentials or AWS signing required")
} Prevention
- Validate elasticsearch.url parses as a URL before starting the server
- Smoke-test the ES endpoint with curl from the server host
- Keep credentials and AWSRequestSigning mutually consistent
- Test datastore configs in CI with a startup dry-run
When it happens
Trigger: Calling temporal.NewServerFx (or NewServer) with a persistence datastore whose Elasticsearch section is set; esclient.NewClient fails, e.g. malformed URL, invalid config fields, or an unusable injected HTTP client.
Common situations: Typo or invalid scheme in the elasticsearch.url config value; missing credentials that the ES client constructor rejects; bad AWSRequestSigning settings; custom elasticsearchHttpClient injection erroring during construction.
Related errors
- unable to create AWS HTTP client for Elasticsearch: %w
- requires a StartTime or CloseTime
- missing current cluster metadata under clusterMetadata.Clust
- failed to get config files: %w
- unable to create metrics handler: %w
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/2ce79689466d2cf5.
Report an issue: GitHub.