jaegertracing/jaeger · error

Field %s is missing a tag 'metric'

Error message

Field %s is missing a tag 'metric'

What it means

metrics.Init() uses reflection over a struct of metric fields and requires every field to carry a `metric:"name"` struct tag identifying it. A field whose metric tag is empty/missing is rejected rather than silently skipped, so the metrics struct is fully defined. This keeps metric registration explicit and prevents unregistered zero-value fields.

Source

Thrown at internal/metrics/metrics.go:55

		factory = NullFactory
	}

	counterPtrType := reflect.TypeFor[Counter]()
	gaugePtrType := reflect.TypeFor[Gauge]()
	timerPtrType := reflect.TypeFor[Timer]()
	histogramPtrType := reflect.TypeFor[Histogram]()

	v := reflect.ValueOf(m).Elem()
	t := v.Type()
	for i := 0; i < t.NumField(); i++ {
		tags := make(map[string]string)
		maps.Copy(tags, globalTags)
		var histogramBuckets []float64
		var timerBuckets []time.Duration
		field := t.Field(i)
		metric := field.Tag.Get("metric")
		if metric == "" {
			return fmt.Errorf("Field %s is missing a tag 'metric'", field.Name)
		}
		if tagString := field.Tag.Get("tags"); tagString != "" {
			for tagPair := range strings.SplitSeq(tagString, ",") {
				tag := strings.Split(tagPair, "=")
				if len(tag) != 2 {
					return fmt.Errorf(
						"Field [%s]: Tag [%s] is not of the form key=value in 'tags' string [%s]",
						field.Name, tagPair, tagString,
					)
				}
				tags[tag[0]] = tag[1]
			}
		}
		if bucketString := field.Tag.Get("buckets"); bucketString != "" {
			switch {
			case field.Type.AssignableTo(timerPtrType):
				bucketValues := strings.Split(bucketString, ",")
				for _, bucket := range bucketValues {

View on GitHub (pinned to 806f444784)

Solutions

  1. Add a `metric:"<name>"` tag to the offending field
  2. Check for a typo like `metirc:` in the tag key
  3. Ensure the tag is on the same line as the field, in backticks
  4. Re-run Init; the error names the exact field, so go straight to it

Example fix

// before
Latency *Timer
// after
Latency *Timer `metric:"latency" help:"request latency"`
Defensive patterns

Strategy: validation

Validate before calling

func checkMetricTags(s any) error {
    t := reflect.TypeOf(s)
    for i := 0; i < t.NumField(); i++ {
        if t.Field(i).Tag.Get("metric") == "" {
            return fmt.Errorf("field %s missing metric tag", t.Field(i).Name)
        }
    }
    return nil
}

Try / catch

if err := metrics.Init(&m); err != nil {
    if strings.Contains(err.Error(), "missing a tag 'metric'") {
        // fix the named field's struct tag
    }
    return err
}

Prevention

When it happens

Trigger: Calling Init/MustInit/NewTable/buildQueryMetrics on a metrics struct where some exported *Timer/*Gauge/*Counter field lacks the `metric` tag entirely or has an empty `metric:""` value.

Common situations: Adding a new field to a metrics struct and forgetting the tag; copy-pasting a field declaration without its tag line; running gofmt/tooling that dropped a malformed tag.

Related errors


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