jaegertracing/jaeger · error
multiple backend types found for metric storage: %v
Error message
multiple backend types found for metric storage: %v
What it means
Same one-backend-per-definition rule as the trace variant, applied to metric storage: MetricBackend.Validate() gathers all populated backend types and rejects any metric backend entry that specifies more than one, returning this error with the list of types found.
Source
Thrown at cmd/internal/storageconfig/config.go:178
func (cfg *MetricBackend) Validate() error {
var backends []string
if cfg.Prometheus != nil {
backends = append(backends, "prometheus")
}
if cfg.Elasticsearch != nil {
backends = append(backends, "elasticsearch")
}
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)
}View on GitHub (pinned to 806f444784)
Solutions
- Keep exactly one backend type field inside each named metric backend entry; remove the extra
- Define separate named metric backends if you genuinely want multiple types available, then reference one per role
- Use the %v list in the error to identify which two types collided and which config keys to delete
- Audit generated/merged config (print the effective YAML) before starting Jaeger
Example fix
// before (config.yaml)
jaeger:
storage:
metric_backends:
metrics:
prometheus:
host: "http://prom:9090"
clickhouse:
address: clickhouse:9000
// after
jaeger:
storage:
metric_backends:
metrics:
prometheus:
host: "http://prom:9090" Defensive patterns
Strategy: validation
Validate before calling
var cfg storageconfig.Config
if err := v.Unmarshal(&cfg); err != nil { return err }
for name, b := range cfg.MetricBackends {
types := 0
for _, set := range []interface{}{b.Prometheus, b.ClickHouse} {
if !reflect.ValueOf(set).IsNil() { types++ }
}
if types > 1 {
return fmt.Errorf("metric backend %q sets %d storage types; keep exactly one", name, types)
}
} Try / catch
if err := cfg.Validate(); err != nil {
if strings.Contains(err.Error(), "multiple backend types found for metric storage") {
// fix the named metric_backends entry named in the message
}
return err
} Prevention
- Exactly one backend type field per named metric backend
- Remove legacy metric backend fields when migrating between backends
- Check merge tooling output for duplicated type keys under one entry
- Validate config in CI before rollout
When it happens
Trigger: Calling Config.Validate() with a MetricBackends entry that has two or more backend fields populated, e.g. both `prometheus:` (remote storage config) and `clickhouse:` set on the same named metric backend.
Common situations: Config merge/Helm values layering that adds a second metric backend type to an existing entry; example configs combined by hand; leftovers of a migration from one metrics backend to another.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- multiple backend types found for trace storage: %v
- trace storage '%s': %w
- metric storage '%s': %w
- no sampling strategy provider specified, expecting 'adaptive
- only one sampling strategy provider can be specified, 'adapt
AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01).
Data as JSON: /api/errors/c5862baaa162c862.
Report an issue: GitHub.