jaegertracing/jaeger · error

invalid version format: %v

Error message

invalid version format: %v

What it means

ping calls the cluster info API and reads the Version["number"] field from the response. That field is expected to be a JSON string (e.g. "8.11.0"); if it is present under the "number" key but is not a string, ping refuses to guess and returns "invalid version format" with the actual value. Callers (ResolveBackendVersion) use this to pick ES vs OpenSearch code paths, so a wrong type would silently break version dispatch.

Source

Thrown at internal/storage/elasticsearch/esclient/version.go:39

		Version map[string]any `json:"version"`
		TagLine string         `json:"tagline"`
	}
	body, err := c.request(ctx, elasticRequest{
		endpoint: "",
		method:   http.MethodGet,
	})
	if err != nil {
		return es.PingResult{}, err
	}
	var info clusterInfo
	if err := json.Unmarshal(body, &info); err != nil {
		return es.PingResult{}, err
	}

	versionField := info.Version["number"]
	versionNumber, isString := versionField.(string)
	if !isString {
		return es.PingResult{}, fmt.Errorf("invalid version format: %v", versionField)
	}
	return es.PingResult{VersionNumber: versionNumber, TagLine: info.TagLine}, nil
}

View on GitHub (pinned to 806f444784)

Solutions

  1. Confirm the endpoint is a real Elasticsearch/OpenSearch node: curl http://host:9200/ and check version.number is a plain string.
  2. Check for proxies/LB that intercept / and return a transformed payload; point the client directly at the cluster.
  3. Update the Elasticsearch/Opensearch client library if the server version changed the info payload serialization.
  4. Inspect the value printed in the error to identify what the server actually returned (null suggests a missing/malformed response body).

Example fix

// before: hitting a proxy that returns {"version":{"number":8.1}}
server: "http://proxy:8080"
// after: hit the ES node directly
server: "http://es-node:9200"
Defensive patterns

Strategy: type-guard

Validate before calling

// verify the endpoint returns a plain ES cluster info first
var info struct {
	Version struct{ Number string `json:"number"` } `json:"version"`
}
if err := json.NewDecoder(resp.Body).Decode(&info); err != nil || info.Version.Number == "" {
	return fmt.Errorf("endpoint does not look like Elasticsearch")
}

Type guard

func versionNumberIsString(info map[string]interface{}) (string, bool) {
	v, ok := info["number"]
	s, isStr := v.(string)
	return s, ok && isStr
}

Try / catch

pr, err := ResolveBackendVersion(ctx, client)
if err != nil {
	if strings.Contains(err.Error(), "invalid version format") {
		// endpoint is not returning a standard cluster-info payload;
		// check what the server actually returned and fix the endpoint
	}
	return err
}

Prevention

When it happens

Trigger: ResolveBackendVersion → ping against a server whose cluster info response has Version["number"] as a non-string (nil, map, or number) — e.g. a proxy or OpenSearch-compatible service returning an unexpected body shape.

Common situations: Pointing Jaeger at a non-Elasticsearch endpoint (proxy, load balancer HTML error page is JSON-wrapped oddly, or a custom mock); upgrading Elasticsearch where the info payload changed; a misconfigured endpoint returning a cluster-info-like body from a different product.

Related errors


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