jaegertracing/jaeger · error

failed to create template: %w

Error message

failed to create template: %w

What it means

Returned by IndicesClient.CreateTemplate when the PUT to _index_template/<name> (v8) or _template/<name> (legacy) fails with a non-ResponseError cause. The template body is rendered internally (RenderIndexTemplate) before the request; if rendering fails, a different error is returned. Structured ES rejections become a prefixMessage variant naming the template.

Source

Thrown at internal/storage/elasticsearch/esclient/index_client.go:311

// callers express pure Jaeger intent and never hold a BackendVersion.
func (i IndicesClient) CreateTemplate(ctx context.Context, name string, mappingType MappingType) error {
	template, err := RenderIndexTemplate(mappingType, i.Indices, i.UseILM, i.ILMPolicyName, i.version)
	if err != nil {
		return err
	}
	_, err = i.request(ctx, elasticRequest{
		endpoint: i.templateEndpoint(name),
		method:   http.MethodPut,
		body:     []byte(template),
	})
	if err != nil {
		var responseError ResponseError
		if errors.As(err, &responseError) {
			if responseError.StatusCode != http.StatusOK {
				return responseError.prefixMessage("failed to create template: " + name)
			}
		}
		return fmt.Errorf("failed to create template: %w", err)
	}
	return nil
}

// Rollover create a rollover for certain index/alias
func (i IndicesClient) Rollover(ctx context.Context, rolloverTarget string, conditions map[string]any) error {
	esReq := elasticRequest{
		endpoint: rolloverTarget + "/_rollover/",
		method:   http.MethodPost,
	}
	if len(conditions) > 0 {
		body := map[string]any{
			"conditions": conditions,
		}
		bodyBytes, err := json.Marshal(body)
		if err != nil {
			return err
		}

View on GitHub (pinned to 806f444784)

Solutions

  1. Verify ES reachability and fix address/TLS/credentials
  2. Retry CreateTemplate — re-PUT of the same template is idempotent
  3. Confirm the jaeger version matches the backend (ES7 vs ES8/OpenSearch) since the endpoint differs
  4. Unwrap the error to distinguish transport failure from an ES-side rejection

Example fix

// before
if err := client.CreateTemplate(ctx, "jaeger-span", esclient.SpanMapping); err != nil {
    return err
}
// after
if err := client.CreateTemplate(ctx, "jaeger-span", esclient.SpanMapping); err != nil {
    var respErr esclient.ResponseError
    if !errors.As(err, &respErr) {
        return retryAfterHealthCheck(err) // transport failure: idempotent retry
    }
    return err
}
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight: cluster health and version compatibility
resp, err := http.Get(esURL + "/_cluster/state/version?filter_path=version.number")
if err != nil || resp.StatusCode != 200 {
    return fmt.Errorf("ES unavailable before template install")
}

Type guard

var respErr esclient.ResponseError
isTransportFailure := !errors.As(err, &respErr)

Try / catch

if err := client.CreateTemplate(ctx, name, mappingType); err != nil {
    var respErr esclient.ResponseError
    if errors.As(err, &respErr) {
        return fmt.Errorf("ES rejected template %s (status %d): %w", name, respErr.StatusCode, err)
    }
    return retryWithBackoff(err) // template PUT is idempotent
}

Prevention

When it happens

Trigger: PUT of the rendered index template fails at the transport layer: connection refused/reset, timeout, canceled context, or an error body that cannot be wrapped as ResponseError.

Common situations: ES restarting while Jaeger initializes its index templates; network misconfiguration on first deployment; extremely short client timeouts on slow clusters; version-dependent test paths (see TestCreateTemplateRenderError) failing before the request.

Related errors


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