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
- Add a `metric:"<name>"` tag to the offending field
- Check for a typo like `metirc:` in the tag key
- Ensure the tag is on the same line as the field, in backticks
- 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
- Always give every metrics-struct field a metric tag when adding it
- Copy the whole field line (including backtick tags) when duplicating fields
- Add a unit test that Initializes all metrics structs
- Avoid hand-editing struct tags without running go vet
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
- Field [%s]: Tag [%s] is not of the form key=value in 'tags'
- Field [%s]: Bucket [%s] could not be parsed as duration in '
- Field [%s]: Bucket [%s] could not be converted to float64 in
- Field [%s]: Buckets should only be defined for Timer and His
- Field %s is not a pointer to timer, gauge, or counter
AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01).
Data as JSON: /api/errors/9cfbbc9443fc3950.
Report an issue: GitHub.