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

  1. Read the wrapped cause at the end of the message and fix that underlying issue (connection refused, 401, x509, etc.).
  2. Verify the Elasticsearch address argument is reachable: curl the URL from the same host/pod.
  3. Add the correct TLS/credential flags (ca, token, username/password) for a secured cluster.
  4. 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

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


AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01). Data as JSON: /api/errors/8c3ff9071a40b428. Report an issue: GitHub.