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 orView on GitHub (pinned to 806f444784)
Solutions
- Check network/TLS/auth so the cluster ping succeeds (curl the ES root endpoint from the Jaeger host)
- Set a valid explicit version in the config to skip probing if probing is unwanted
- Verify ES is running and the configured addresses are correct
- 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
- Set an explicit, valid version in config to skip probing
- Include ES connectivity checks in readiness probes
- Keep TLS certs and credentials current
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
- error creating Elasticsearch client: %w
- failed to create Elasticsearch client: %w
- invalid version format: %s
- failed to delete indices: %w
- failed to create index: %w
AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01).
Data as JSON: /api/errors/3ec55ae2a1016407.
Report an issue: GitHub.