jaegertracing/jaeger · error
Field %s is not a pointer to timer, gauge, or counter
Error message
Field %s is not a pointer to timer, gauge, or counter
What it means
metrics.Init() reflects over struct fields and only knows how to instantiate *Timer, *Gauge, and *Counter fields. A field with any other type (or a non-pointer metric type) falls into the default case and returns this error naming the field, because the library cannot allocate a metric object for it.
Source
Thrown at internal/metrics/metrics.go:132
Tags: tags,
Help: help,
})
case field.Type.AssignableTo(timerPtrType):
obj = factory.Timer(TimerOptions{
Name: metric,
Tags: tags,
Help: help,
Buckets: timerBuckets,
})
case field.Type.AssignableTo(histogramPtrType):
obj = factory.Histogram(HistogramOptions{
Name: metric,
Tags: tags,
Help: help,
Buckets: histogramBuckets,
})
default:
return fmt.Errorf(
"Field %s is not a pointer to timer, gauge, or counter",
field.Name,
)
}
v.Field(i).Set(reflect.ValueOf(obj))
}
return nil
}
View on GitHub (pinned to 806f444784)
Solutions
- Change the field to a *Timer, *Gauge, or *Counter pointer
- Add the missing '*' to make the field a pointer
- Move non-metric fields out of the metrics struct
- Check the import: use the timer/gauge/counter types this package expects
Example fix
// before Latency timer.Timer `metric:"latency"` // after Latency *timer.Timer `metric:"latency"`
Defensive patterns
Strategy: type-guard
Validate before calling
func checkMetricFieldTypes(s any) error {
t := reflect.TypeOf(s)
for i := 0; i < t.NumField(); i++ {
ft := t.Field(i).Type
if ft.Kind() != reflect.Pointer {
return fmt.Errorf("field %s must be a pointer metric", t.Field(i).Name)
}
}
return nil
} Type guard
func isSupportedMetricField(t reflect.StructField) bool {
return t.Type.AssignableTo(timerPtrType) ||
t.Type.AssignableTo(gaugePtrType) ||
t.Type.AssignableTo(counterPtrType)
} Prevention
- Declare metric fields only as *Timer, *Gauge, or *Counter pointers
- Never put non-metric helper fields in the metrics struct
- Always use pointer types — value types hit the default branch
- Compile-time check: var _ *timer.Timer = (*metricsStruct).field pattern or a small init test
When it happens
Trigger: A metrics struct containing a field of a type other than *timer.Timer, *gauge.Gauge, or *counter.Counter (e.g. a plain Timer value without pointer, a string/int helper field, or a custom metric type) when Init runs.
Common situations: Adding metadata or non-metric fields to the metrics struct; forgetting the '*' so the field is a value instead of a pointer; using a metric type from another package the Init switch does not recognize.
Related errors
- Field %s is missing a tag 'metric'
- 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
AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01).
Data as JSON: /api/errors/d4ef9a29833c68da.
Report an issue: GitHub.