jaegertracing/jaeger · error

multiple backend types found for trace storage: %v

Error message

multiple backend types found for trace storage: %v

What it means

MetricBackend/TraceBackend Validate() collects every backend type present in a single storage definition (memory, badger, cassandra, elasticsearch/opensearch, grpc, clickhouse). A Jaeger storage backend must be exactly one type; if the same backend block sets more than one storage type, Validate returns this error listing the conflicting types.

Source

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

		backends = append(backends, "grpc")
	}
	if cfg.Cassandra != nil {
		backends = append(backends, "cassandra")
	}
	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 trace storage: %v", backends)
	}
	return nil
}

// Unmarshal implements confmap.Unmarshaler for MetricBackend.
func (cfg *MetricBackend) Unmarshal(conf *confmap.Conf) error {
	// apply defaults
	if conf.IsSet("prometheus") {
		v := prometheus.DefaultConfig()
		cfg.Prometheus = &PrometheusConfiguration{
			Configuration: v,
		}
	}
	if conf.IsSet("elasticsearch") {
		v := es.DefaultConfig()
		cfg.Elasticsearch = &v
	}
	if conf.IsSet("opensearch") {

View on GitHub (pinned to 806f444784)

Solutions

  1. Edit the named trace backend in your config so exactly one storage type field is set (delete the others)
  2. If you need two storage types, define them as two separate named backends under jaeger.storage.trace_backends and use jaeger.storage.backends to pick per-role
  3. Inspect the error's %v list — it names the conflicting types found (e.g. [cassandra elasticsearch]) so you know which fields to remove
  4. Check any config-merge tooling (Helm/Kustomize) for values that add fields to an existing backend entry

Example fix

// before (config.yaml)
jaeger:
  storage:
    trace_backends:
      main:
        memory: {}
        cassandra:
          servers: cassandra:9042
// after
jaeger:
  storage:
    trace_backends:
      main:
        cassandra:
          servers: cassandra:9042
Defensive patterns

Strategy: validation

Validate before calling

import "github.com/jaegertracing/jaeger/cmd/internal/storageconfig"
var cfg storageconfig.Config
if err := v.Unmarshal(&cfg); err != nil { return err }
for name, b := range cfg.TraceBackends {
    types := 0
    for _, set := range []interface{}{b.Memory, b.Badger, b.Cassandra, b.Elasticsearch, b.GRPC, b.ClickHouse} {
        if !reflect.ValueOf(set).IsNil() { types++ }
    }
    if types > 1 {
        return fmt.Errorf("trace 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 trace storage") {
        // parse the listed types from the message and fix that named entry
    }
    return err
}

Prevention

When it happens

Trigger: Calling Config.Validate() (invoked when Jaeger loads the storage configuration) with one TraceBackends entry that populates more than one of the backend fields, e.g. both `memory:` and `cassandra:` set under the same named backend.

Common situations: Merging YAML fragments (e.g. Helm values or env overlays) that each set a different storage type on the same named backend; copy-pasting an example backend block and forgetting to delete the old fields; a default value left populated alongside an explicitly configured backend.

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


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