jaegertracing/jaeger · error
error creating Elasticsearch client: %w
Error message
error creating Elasticsearch client: %w
What it means
This error is returned by the es-index-cleaner command when app.NewESClient fails to construct the Elasticsearch client after the config has loaded successfully. It wraps the underlying cause (%w), so the real reason (unreachable host, bad credentials, unsupported scheme) is appended to this message. It is a fatal startup error: the cleaner cannot do any work without a client.
Source
Thrown at cmd/es-index-cleaner/main.go:72
Short: "Jaeger es-index-cleaner removes Jaeger indices",
Long: "Jaeger es-index-cleaner removes Jaeger indices",
RunE: func(_ *cobra.Command, args []string) error {
if len(args) != 2 {
return errors.New("wrong number of arguments")
}
numOfDays, err := strconv.Atoi(args[0])
if err != nil {
return fmt.Errorf("could not parse NUM_OF_DAYS argument: %w", err)
}
if err := cfg.InitFromViper(v); err != nil {
return fmt.Errorf("failed to initialize config: %w", err)
}
ctx := context.Background()
esClient, err := app.NewESClient(ctx, args[1], cfg, logger)
if err != nil {
return fmt.Errorf("error creating Elasticsearch client: %w", err)
}
i := esclient.IndicesClient{
Client: esClient,
MasterTimeoutSeconds: cfg.MasterNodeTimeoutSeconds,
IgnoreUnavailableIndex: true,
}
indices, err := i.GetJaegerIndices(ctx, cfg.IndexPrefix)
if err != nil {
return err
}
deleteIndicesBefore := app.CalculateDeletionCutoff(time.Now().UTC(), numOfDays, relativeIndexCleaner.IsEnabled())
logger.Info("Indices before this date will be deleted", zap.String("date", deleteIndicesBefore.Format(time.RFC3339)))
filter := &app.IndexFilter{
IndexPrefix: cfg.IndexPrefix,
IndexDateSeparator: cfg.IndexDateSeparator,View on GitHub (pinned to 806f444784)
Solutions
- Read the wrapped cause at the end of the message and fix that underlying issue (connection refused, 401, x509, etc.).
- Verify the Elasticsearch address argument is reachable: curl the URL from the same host/pod.
- Add the correct TLS/credential flags (ca, token, username/password) for a secured cluster.
- Ensure Elasticsearch is ready before the cleaner runs (init-container readiness check or retry logic).
Example fix
// before
esClient, err := app.NewESClient(ctx, "http://es:9200", cfg, logger)
// after — pass flags-derived config with auth/TLS set and verify URL first
if err := verifyESURL(esURL); err != nil { ... }
esClient, err := app.NewESClient(ctx, esURL, cfg, logger) Defensive patterns
Strategy: validation
Validate before calling
esURL := args[1]
u, err := url.Parse(esURL)
if err != nil || u.Scheme == "" || u.Host == "" {
return fmt.Errorf("invalid ES URL %q", esURL)
}
resp, err := http.Get(esURL)
if err != nil { return fmt.Errorf("ES unreachable: %w", err) }
resp.Body.Close() Try / catch
if err := run(); err != nil {
var esErr *app.ESClientError
if errors.As(err, &esErr) { /* inspect wrapped cause */ }
log.Fatal(err)
} Prevention
- Curl the ES URL from the same pod/host before deploying the cleaner.
- Use readiness-gated init containers so ES is up first.
- Always pass TLS/auth flags when the cluster has security enabled.
- Check the wrapped cause, not just the wrapper message.
When it happens
Trigger: Running es-index-cleaner with an Elasticsearch address argument that is unreachable, malformed, or requires auth/TLS that is not configured; NewESClient fails during ping/version discovery (e.g. trying to detect ES version via the root endpoint).
Common situations: Elasticsearch not yet up when a Kubernetes init-container/cronjob runs the cleaner; wrong ES URL or port; missing TLS/credential flags for a secured cluster; ES behind a proxy that blocks the version probe.
Related errors
- failed to create Elasticsearch client: %w
- failed to resolve backend version: %w
- invalid server URL %q: %w
- failed to discover Elasticsearch nodes (sniffing): %w
- file must begin with '['
AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01).
Data as JSON: /api/errors/8c3ff9071a40b428.
Report an issue: GitHub.