jaegertracing/jaeger · error

failed to resolve backend version: %w

Error message

failed to resolve backend version: %w

What it means

NewClient must know the Elasticsearch backend version to pick correct APIs. It honors an explicit configured Version or probes the cluster once via a low-level ping (ResolveBackendVersion); if the configured version is invalid or the ping fails, the error is wrapped with this message and client creation fails.

Source

Thrown at internal/storage/elasticsearch/esclient/client.go:66

	if err != nil {
		return nil, err
	}
	transport, err := newRawClient(ctx, base, rawClientOptions{
		servers:             c.Servers,
		compressRequestBody: c.HTTPCompression,
		discoverNodes:       c.Sniffing.Enabled,
		logLevel:            c.LogLevel,
		logger:              logger,
	})
	if err != nil {
		return nil, err
	}
	client := &Client{transport: transport, timeout: c.QueryTimeout}
	// Honor an explicit c.Version, otherwise probe the cluster once via the
	// low-level ping. Both planes share es.ResolveBackendVersion.
	version, err := es.ResolveBackendVersion(ctx, c.Version, client.ping)
	if err != nil {
		return nil, fmt.Errorf("failed to resolve backend version: %w", err)
	}
	client.version = version
	return client, nil
}

// Close releases the client's pooled idle connections. It is safe to call on a nil
// *Client (a factory that failed to construct one). The transport has no background
// goroutines — node discovery (sniffing), when enabled, runs once at startup rather
// than on a schedule — so there is nothing else to stop.
func (c *Client) Close() error {
	if c != nil && c.transport != nil {
		c.transport.close()
	}
	return nil
}

// TestsOnlyBackendVersion returns the backend version resolved at construction.
// It exists ONLY for integration tests that must branch on the backend flavor or

View on GitHub (pinned to 806f444784)

Solutions

  1. Check network/TLS/auth so the cluster ping succeeds (curl the ES root endpoint from the Jaeger host)
  2. Set a valid explicit version in the config to skip probing if probing is unwanted
  3. Verify ES is running and the configured addresses are correct
  4. Inspect the wrapped inner error for the root cause (dial failure vs parse failure)

Example fix

// before
version: v7   # unparsable
// after
version: 7.17.0
Defensive patterns

Strategy: try-catch

Validate before calling

// preflight: confirm the cluster answers the root endpoint
resp, err := http.Get(esURL)
if err != nil {
    return fmt.Errorf("ES unreachable before client init: %w", err)
}
resp.Body.Close()

Try / catch

client, err := esclient.NewClient(ctx, cfg, transport, logger)
if err != nil {
    if strings.Contains(err.Error(), "failed to resolve backend version") {
        logger.Error("ES version probe failed; check connectivity/TLS/auth or set an explicit version", "err", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling NewClient when c.Version is set to an unparsable value, or when the cluster ping fails (unreachable host, TLS/auth failure, no healthy nodes).

Common situations: Typo in the version config (e.g. 'v7' instead of a parseable version); ES down or behind a proxy that blocks the ping endpoint; wrong TLS certificates; DNS/network issues in Kubernetes.

Related errors


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