jaegertracing/jaeger · error

at least one storage backend is required

Error message

at least one storage backend is required

What it means

errUnsupportedField reports that the named built-in field of the given level (a reference like duration, service name, etc.) is not supported by this backend's filter engine. The filter is rejected with tracestore.ErrFilterUnsupported since the engine has no mapping from that built-in field to an indexed Elasticsearch field.

Source

Thrown at cmd/internal/storageconfig/config.go:186

	if cfg.Opensearch != nil {
		backends = append(backends, "opensearch")
	}
	if cfg.ClickHouse != nil {
		backends = append(backends, "clickhouse")
	}
	if len(backends) == 0 {
		return errors.New("empty configuration")
	}
	if len(backends) > 1 {
		return fmt.Errorf("multiple backend types found for metric storage: %v", backends)
	}
	return nil
}

// Validate validates the storage configuration.
func (c *Config) Validate() error {
	if len(c.TraceBackends) == 0 {
		return errors.New("at least one storage backend is required")
	}
	for name, b := range c.TraceBackends {
		if err := b.Validate(); err != nil {
			return fmt.Errorf("trace storage '%s': %w", name, err)
		}
	}
	for name, b := range c.MetricBackends {
		if err := b.Validate(); err != nil {
			return fmt.Errorf("metric storage '%s': %w", name, err)
		}
	}
	return nil
}

View on GitHub (pinned to 806f444784)

Solutions

  1. Use a built-in field name the backend supports (verify against the tracestore's field list/capabilities).
  2. Move the value into a span attribute and filter on the attribute instead of the unsupported built-in field.
  3. Upgrade the backend if the field is supported in a newer version.

Example fix

// before
{"field": "client.city", "op": "eq", "value": "NYC"}
// after
{"attr": "client.city", "op": "eq", "value": "NYC"}
Defensive patterns

Strategy: validation

Validate before calling

var builtinFields = map[string]bool{"duration": true, /* ...supported set... */ }
func fieldSupported(name string) bool { return builtinFields[name] }

Try / catch

q, err := buildComparison(ref, op, value)
if errors.Is(err, tracestore.ErrFilterUnsupported) && strings.Contains(err.Error(), "built-in field") {
    // use a supported field or an attribute instead
}

Prevention

When it happens

Trigger: Submitting a filter that dereferences a built-in field on a level where buildComparison/buildExists has no case for it — e.g. a built-in field name that exists in the expression model but is not mapped in this tracestore.

Common situations: Using a field added in a newer expression model than the deployed backend supports; typos or case differences in built-in field names; copying filters from backends with richer built-in field sets.

Related errors


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