grafana/k6 · error · ErrInvalidMetricType
invalid metric type
Error message
invalid metric type
What it means
ErrInvalidMetricType (metrics/metric_type.go:20) is returned by MetricType.UnmarshalText (line 70) when the string being deserialized is not one of 'counter', 'gauge', 'trend', 'rate' — and symmetrically by MarshalText (line 54) for an out-of-range MetricType integer. It surfaces through UnmarshalJSON/MarshalJSON whenever a metric's serialized type round-trips: registry JSON, k6 archive inspection, or summary/output serialization.
Source
Thrown at metrics/metric_type.go:20
import (
"errors"
"slices"
)
// A MetricType specifies the type of a metric.
type MetricType int
// Possible values for MetricType.
const (
Counter = MetricType(iota) // A counter that sums its data points
Gauge // A gauge that displays the latest value
Trend // A trend, min/max/avg/med are interesting
Rate // A rate, displays % of values that aren't 0
)
// ErrInvalidMetricType indicates the serialized metric type is invalid.
var ErrInvalidMetricType = errors.New("invalid metric type")
const (
counterString = "counter"
gaugeString = "gauge"
trendString = "trend"
rateString = "rate"
defaultString = "default"
timeString = "time"
dataString = "data"
)
// MarshalJSON serializes a MetricType as a human readable string.
func (t MetricType) MarshalJSON() ([]byte, error) {
txt, err := t.MarshalText()
if err != nil {
return nil, err
}View on GitHub (pinned to 93accf6570)
Solutions
- Use exactly one of: counter, gauge, trend, rate (lowercase)
- If interoperating with an older format, map legacy names to the four supported types before unmarshaling
- When the value comes from user input, validate it against the accepted set before decoding
Example fix
// before var mt metrics.MetricType err := json.Unmarshal([]byte(`"Histogram"`), &mt) // ErrInvalidMetricType // after var mt metrics.MetricType err := json.Unmarshal([]byte(`"trend"`), &mt)
Defensive patterns
Strategy: type-guard
Validate before calling
// Go: whitelist check before unmarshaling external strings
var validMetricTypes = map[string]bool{"counter": true, "gauge": true, "trend": true, "rate": true}
if !validMetricTypes[input] {
return fmt.Errorf("unsupported metric type %q; want counter|gauge|trend|rate", input)
} Type guard
// Go
func isValidMetricType(s string) bool {
switch s {
case "counter", "gauge", "trend", "rate":
return true
}
return false
} Try / catch
// Go
if err := json.Unmarshal(data, &mt); err != nil {
if errors.Is(err, metrics.ErrInvalidMetricType) {
// map legacy names (e.g. "histogram" -> "trend") and retry, or reject input
}
} Prevention
- k6 metric types are exactly counter, gauge, trend, rate — lowercase and case-sensitive
- When ingesting third-party metric JSON, normalize type names before decoding
When it happens
Trigger: json.Unmarshal into a struct with a metrics.MetricType field given '"histogram"', '"COUNTER"' (case-sensitive), or '""'; marshaling a MetricType constructed from an invalid int like MetricType(7).
Common situations: Consuming metric payloads from old k6 versions or third-party tools that emit legacy type names (e.g. pre-0.4 'histogram' types); hand-built JSON metric definitions with typos or wrong casing; corrupted exported archives.
Related errors
- invalid value type
- unmarshalling options for SDK: %w
- unmarshalling image format: %w
- only arrays can be made into SharedArray
- invalid threshold
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/28f48810aa028667.
Report an issue: GitHub.