{"record":{"id":"d4ef9a29833c68da","repo":"jaegertracing/jaeger","slug":"field-s-is-not-a-pointer-to-timer-gauge-or-coun","errorCode":null,"errorMessage":"Field %s is not a pointer to timer, gauge, or counter","messagePattern":"Field (.+?) is not a pointer to timer, gauge, or counter","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/metrics/metrics.go","lineNumber":132,"sourceCode":"\t\t\t\tTags: tags,\n\t\t\t\tHelp: help,\n\t\t\t})\n\t\tcase field.Type.AssignableTo(timerPtrType):\n\t\t\tobj = factory.Timer(TimerOptions{\n\t\t\t\tName:    metric,\n\t\t\t\tTags:    tags,\n\t\t\t\tHelp:    help,\n\t\t\t\tBuckets: timerBuckets,\n\t\t\t})\n\t\tcase field.Type.AssignableTo(histogramPtrType):\n\t\t\tobj = factory.Histogram(HistogramOptions{\n\t\t\t\tName:    metric,\n\t\t\t\tTags:    tags,\n\t\t\t\tHelp:    help,\n\t\t\t\tBuckets: histogramBuckets,\n\t\t\t})\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\n\t\t\t\t\"Field %s is not a pointer to timer, gauge, or counter\",\n\t\t\t\tfield.Name,\n\t\t\t)\n\t\t}\n\t\tv.Field(i).Set(reflect.ValueOf(obj))\n\t}\n\treturn nil\n}\n","sourceCodeStart":114,"sourceCodeEnd":141,"githubUrl":"https://github.com/jaegertracing/jaeger/blob/806f4447841ecdb60519f408b004a599d515f437/internal/metrics/metrics.go#L114-L141","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nLatency timer.Timer `metric:\"latency\"`\n// after\nLatency *timer.Timer `metric:\"latency\"`","handlingStrategy":"type-guard","validationCode":"func checkMetricFieldTypes(s any) error {\n    t := reflect.TypeOf(s)\n    for i := 0; i < t.NumField(); i++ {\n        ft := t.Field(i).Type\n        if ft.Kind() != reflect.Pointer {\n            return fmt.Errorf(\"field %s must be a pointer metric\", t.Field(i).Name)\n        }\n    }\n    return nil\n}","typeGuard":"func isSupportedMetricField(t reflect.StructField) bool {\n    return t.Type.AssignableTo(timerPtrType) ||\n        t.Type.AssignableTo(gaugePtrType) ||\n        t.Type.AssignableTo(counterPtrType)\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["reflection","struct-tags","metrics","type-error"],"backgroundTag":"invalid-metric-field-type","analyzedSha":"806f4447841ecdb60519f408b004a599d515f437","analyzedAt":"2026-09-01T02:39:22.140Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}