jaegertracing/jaeger · error

unexpected metrics ValueType: %s

Error message

unexpected metrics ValueType: %s

What it means

The Prometheus Translator.ToDomainMetricsFamily expects Prometheus query results as a model.Matrix (range vector), since Jaeger metrics are returned as time series. If the model.Value's type is anything other than model.ValMatrix (e.g. ValVector, ValScalar, ValString), translation is impossible and this error reports the unexpected value type.

Source

Thrown at internal/storage/metricstore/prometheus/metricstore/dbmodel/to_domain.go:31

)

// Translator translates Prometheus's metrics model to Jaeger's.
type Translator struct {
	labelMap map[string]string
}

// New returns a new Translator.
func New(spanNameLabel string) Translator {
	return Translator{
		// "operation" is the label name that Jaeger UI expects.
		labelMap: map[string]string{spanNameLabel: "operation"},
	}
}

// ToDomainMetricsFamily converts Prometheus' representation of metrics query results to Jaeger's.
func (d Translator) ToDomainMetricsFamily(name, description string, mv model.Value) (*metrics.MetricFamily, error) {
	if mv.Type() != model.ValMatrix {
		return &metrics.MetricFamily{}, fmt.Errorf("unexpected metrics ValueType: %s", mv.Type())
	}
	return &metrics.MetricFamily{
		Name:    name,
		Type:    metrics.MetricType_GAUGE,
		Help:    description,
		Metrics: d.toDomainMetrics(mv.(model.Matrix)),
	}, nil
}

// toDomainMetrics converts Prometheus' representation of metrics to Jaeger's.
func (d Translator) toDomainMetrics(matrix model.Matrix) []*metrics.Metric {
	ms := make([]*metrics.Metric, matrix.Len())
	for i, ss := range matrix {
		ms[i] = &metrics.Metric{
			Labels:       d.toDomainLabels(ss.Metric),
			MetricPoints: toDomainMetricPoints(ss.Values),
		}
	}

View on GitHub (pinned to 806f444784)

Solutions

  1. Use a range query (query_range) so Prometheus returns a model.Matrix.
  2. Verify the PromQL expression selects an existing metric series over a range (e.g. rate(...[5m])).
  3. Check the caller that fetched mv: it must pass mv from a Matrix-typed response, not a Vector.
  4. Add a caller-side check `if mv.Type() != model.ValMatrix { ... }` before invoking the translator.

Example fix

// before
fam, err := translator.ToDomainMetricsFamily(name, desc, result.Vector)
// after
if result.Value.Type() != model.ValMatrix {
  return nil, fmt.Errorf("expected matrix, got %s", result.Value.Type())
}
fam, err := translator.ToDomainMetricsFamily(name, desc, result.Value)
Defensive patterns

Strategy: type-guard

Validate before calling

if mv.Type() != model.ValMatrix {
  return fmt.Errorf("expected range-vector (matrix) result, got %s; use query_range", mv.Type())
}

Type guard

func isMatrix(v model.Value) (model.Matrix, bool) {
  m, ok := v.(model.Matrix)
  return m, ok && v.Type() == model.ValMatrix
}

Try / catch

fam, err := translator.ToDomainMetricsFamily(name, desc, mv)
if err != nil {
  log.Printf("prometheus result unusable: %v", err) // names the actual type
  return nil, err
}

Prevention

When it happens

Trigger: Calling ToDomainMetricsFamily with a result from a Prometheus query that returned an instant vector/scalar instead of a matrix — e.g. using an instant query API response or a query expression yielding a scalar.

Common situations: Feeding results from /api/v1/query (instant) instead of /api/v1/query_range; a metric name typo causing Prometheus to return an empty/scalar-typed value; custom storage plugins passing the wrong model.Value variant.

Related errors


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